Sei sulla pagina 1di 3

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.

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.

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.

The ExecutorService supports the exectute() method, but it also adds a submit() method
that allows you to query your threads for their return value.

The Executors class provides the following factory methods for creating ExecutorService
instances:

• newCachedThreadPool() : Creates a thread pool that creates new threads as


needed, but will reuse previously constructed threads when they are available.
• newFixedThreadPool(int nThreads): Creates a thread pool that reuses a fixed
number of threads operating off a shared unbounded queue.
• newSingleThreadExecutor() : Creates an Executor that uses a single worker
thread operating off an unbounded queue.
• newScheduledThreadPool(int corePoolSize) : Creates a thread pool that can
schedule commands to run after a given delay, or to execute periodically.
• newSingleThreadScheduledExecutor() : Creates a single-threaded executor that
can schedule commands to run after a given delay, or to execute periodically.
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. You can stop the threads with

executor.shutdown();

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.

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.

Potrebbero piacerti anche