Home : Course Map : Chapter 10 : Java :
The Concurrency Utilities - J2SE5.0
JavaTech
Course Map
Chapter 10

Introduction
Vector/Enumeration
Hashtable,HashMap
   Properties
Collections

Iterator/ArrayList
Generics
Preferences API
  Demo 1
Concurrency Utils
Enumerated Type
Arrays Class
String Tools
  String
  StringBuffer
  StringBuilder
  StringTokenizer
  String.split()

Calendar,Date,Time
  Demo 2
  Demo 3

Other Utilities
Exercises

    Supplements
Performance
Benchmarks
     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

As mentioned in Chapter 8, J2SE5.0 adds numerous enhancements to the threading control and concurrency features of Java. Some of the enhancements are advanced features beyond the scope of this book, but we explain some of the simpler new features here.


The Executor Class

The most important new feature for the casual developer of multithreaded applications is the new Executor framework. A java.util.concurrent.Executor is an object that executes Runnable tasks. It is similar to calling

new Thread (aRunnableObject).start ();

For a single new thread, there is perhaps not much reason to use an Executor. However, most multithreaded applications involve several threads. Threads need stack and heap space, and, depending on the platform, thread creation can be expensive. In addition, cancellation and shutdown of threads can be difficult, as seen in Chapter 8, and a well-designed and implemented thread pooling scheme is not simple.

The new Executor framework solves all those problems in a way that decouples task submission from the mechanics of how each task will be run, including the details of thread use, scheduling, etc.

An Executor can and should be used instead of explicitly creating threads. For example, rather than creating a new thread and starting it as above, you can use:

Executor executor = some Executor factory method;
exector.execute (aRunnable);

Notice that our Executor object was returned by an Executor factory. (We discuss design patterns like factory methods in Chapter 16; a factory is a standard name for a method that is used to obtain an instance of a class or subclass rather than making it with a constructor.)

There are several static Executor factory methods available in the java.util.concurrent.Executors class. If you have several Runnable tasks to carry out, but do not have specific requirements about the order in which they occur, then a simple thread pool arrangement is provided as follows:

Executor executor = Executors.newFixedThreadPool (5);
executor.execute (new RunnableTask1 ());
executor.execute (new RunnableTask2 ());
executor.execute (new RunnableTask3 ());
...

Here the tasks run and complete under the control of the Executor, which reuses threads from the thead pool as needed without incurring the overhead of always creating new threads.

The newFixedThreadPool () method actually returns an object of type ExecuterService, which is a subinterface of Executer. The ExecuterService includes a number of methods for managing a thread pool. For example, the above pool could be stopped with

((ExecuterService)executor).shutdown();

As explained in the specification, this means that no further tasks can be submitted and currently running threads will continue until they finish. The shutdownNow() method will make "best-effort attempts to stop processing actively executing tasks", but there is no guarantee that a thread will be stopped (e.g. if it is in an endless loop in the run() method.) See Chapter 8: Java: Stopping Threads for advice on properly killing a thread.

There are several more Executor factories in the Executors class for other needs beyond the scope of this book. Refer to the J2SE 5.0 API docs for complete information.

The Callable Interface

The new java.util.concurrent.Callable interface is much like Runnable but overcomes two drawbacks with Runnable. The run() method in Runnable cannot return a result (i.e. it returns void) and cannot throw a checked exception. If you try to throw an exception in a run() method, the javac compiler insists that you use a throws clause in the method signature. However, the superclass run() method doesn't throw an exception, so javac will not accept this.

If you need a result from a Runnable task, you have to provide some external means of getting that result. A common technique is to set an instance variable in the Runnable object and provide a method to retrieve that value. For example,

public MyRunnable implements Runnable
{
  private int fResult = 0;
  public void run () {
    ...
    fResult = 1;
  } // run

  // A getter method to provide the result of the thread.
  public int getResult () { return fResult; }

} // class MyRunnable

The Callable interface solves these problems. Instead of a run() method the Callable interface defines a single call() method that takes no parameters but is allowed to throw an exception. A simple example is

import java.util.concurrent.*;
public class MyCallable implements Callable
{
  public Integer call () throws java.io.IOException {
    return 1;
  }
} // MyCallable

This call() method returns an Integer. (Note that we have conveniently used the autoboxing support in J2SE 5.0 to have the literal int 1 value automatically boxed into an Integer return value.)

Getting the return value from a Callable depends upon the new generics feature:

FutureTask task = new FutureTask (new MyCallable ());
ExecutorService es = Executors.newSingleThreadExecutor ();
es.submit (task);
try {
  int result = task.get ();
  System.out.println ("Result from task.get () = " + result);
}
catch (Exception e) {
  System.err.println (e);
}
es.shutdown ();

Here, we use the FutureTask class that supports an Integer return value. Then the task is submitted using the ExecutorService submit() method, and the result is obtained from the FutureTask get() method, again using auto-unboxing to convert the Integer to an int. See the API documentation for more information on ExecutorService, and FutureTask.

Other Concurrency Enhancements

We discuss some other new concurrency tools in Chapter 8: Supplements: More About Concurrency. Other enhancements in the java.util.concurrency package not discussed here include advanced atomic types, new high-performance thread-safe collections ConcurrentHashMap, CopyOnWriteArrayList, and CopyOnWriteArraySet. See the API documentation for more information on these new collections and other features.


References & Web Resources

 

Latest update: Apr.30, 2006

              Tech
ArbitaryPrecision
   BigInteger
  
BigDecimal
Bit Handling
Exercises

           Physics
Data Gen&Analysis

  Demo 1
  Demo 2
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.