The Executor Interface Concurrency Utilities

J.E.D.I.

9.7 Concurrency Utilities

With the release of J2SE5.0, new threading control and concurrency features were added to Java. These new features are found in the java.util.concurrent package. In this section, two of these concurrency features are explained.

9.7.1 The Executor Interface

One of the most important enhancement features for developing multithreaded applications is the Executor framework. The interface is included in the java.util.concurrent package. Objects of this type executes the Runnable tasks. Without the use of this interface, we execute Runnable tasks by creating Thread instances and calling the start method of the the Thread object. The following code demonstrates a way of doing this: new ThreadaRunnableObject.start; With the availability of this new interface, submitted Runnable objects are executed using its execute method as follows: anExecutorObject.executeaRunnableObject; The new Executor framework is useful for multithreaded applications. Because threads need stack and heap space, thread creation can be expensive. As a result, creation of several threads may cause out of memory errors. A way to get around this problem is with thread pooling. In thread pooling, a thread is queued to the pool after it completes its assigned task rather than dying or terminating. However, implementing a well- designed thread pooling scheme is not simple. Another problem was the difficulty in cancellation and shutting down of threads. The Executor framework solves these problems by decoupling task submission from the mechanics of how each task will be run, including details of thread use, scheduling and others. It is normally used instead of explicitly creating threads. Rather than creating a thread and running it via the start method for each set of task, it is more advisable to use the following code fragment instead: Executor executorName = anExecutorObject; executorName.executenew RunnableTask1; executorName.executenew RunnableTask2; ... Since Executor is an interface, it cannot be instantiated. To create an Executor object, one has to create a class implementing this interface or use a factory method provided in the Executors class. This class is also available in the same package as the Executor interface. The Executors class also provide factory methods for simple thread pool management. Here is a summary of some of these factory methods: Executors Factory Methods public static ExecutorService newCachedThreadPool Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. An overloaded method, which also takes in a ThreadFactory object as an argument. public static ExecutorService newFixedThreadPoolint nThreads Introduction to Programming II Page 136 J.E.D.I. Creates a thread pool that reuses a fixed set of threads operating off a shared unbounded queue. An overloaded method, which takes in a ThreadFactory object as an additional parameter. public static ScheduledExecutorService newScheduledThreadPoolint corePoolSize Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically. An overloaded method, which takes in a ThreadFactory object as an additional parameter. public static ExecutorService newSingleThreadExecutor Creates an Executor that uses a single worker thread operating off an unbounded queue. An overloaded method, which also takes in a ThreadFactory object as an argument. public static ScheduledExecutorService newSingleThreadScheduledExecutor Creates a single-threaded executor that can schedule commands to run after a given delay, or to execute periodically. An overloaded method, which also takes in a ThreadFactory object as an argument. Table 33: Factory Methods of the Executors Class The Runnable tasks are executed and finished under the control of the Executor interface. To stop the threads, we can simply invoke the shutdown method of the interface as follows: executor.shutdown;

9.7.2 The Callable Interface