Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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
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:
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:
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 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,
} // 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
Getting the return value from a Callable depends upon the new generics feature:
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.