Java Reference
In-Depth Information
The java.util.concurrent.Executors class provides static factory methods for creating executor ob-
jects. I introduce you to java.util.concurrent.ExecutorService objects as an example of how you can
use an executor. You can create an ExecutorService object like this:
ExecutorService threadPool = Executors.newCachedThreadPool();
This creates an object that creates new threads as required. Each time you use the threadPool object to
start another task, either an existing thread in the pool that is currently no longer running is used, or a new
thread is created and added to the thread pool. If you want to limit the number of threads that might be cre-
ated, you can create a thread pool with a fixed number of threads, like this:
int nThreads = 5;
ExecutorService threadPool = Executors.newFixedThreadPool(nThreads);
This fragment creates a thread pool that contains up to nThreads threads. Starting a new task using
the threadPool object results in the task being executed in a new thread as long as there are fewer than
nThreads threads already in operation. If all threads in the pool have been allocated, the new task is placed
in a queue to wait until one of the existing threads becomes free. All the threads in the pool continue to exist
until threadPool is shut down. The method throws an exception of type IllegalArgumentException if
you specify the maximum number of threads to be less than 1.
ExecutorService is an interface type that is implemented by several classes in the
java.util.concurrent package. Both of the methods from the Executors class that I have introduced
return a reference to an object of type ThreadPoolExecutor , and the functionality is described by the Ex-
ecutorService interface. Let's look at how you use a ThreadPoolExecutor object.
Working with an Executor
The methods specified by the ExecutorService interface enable you to submit new tasks to be executed in
a new thread or an existing unused thread within a thread pool. The interface declares three versions of the
submit() method: two for starting tasks that are Runnable objects and one for starting Callable<> tasks.
You start a Runnable task like this:
ExecutorService threadPool = Executors.newCachedThreadPool();
Future<?> future = threadPool.submit(clerk1);
This fragment starts the Runnable task, clerk1 , that is a Clerk object from the previous example. In
general, the submit() method returns a reference of type java.util.concurrent.Future<V> that reflects
the state of the task at any time, and eventually encapsulates the result of executing a task, the result being of
type V . A Runnable task does not return a result so the value returned by submit will be of type Future<?> .
The second submit() method for a Runnable task accepts a second argument of type V that specifies the
result that is to be returned when the task completes. This enables you to ensure that the result you specify
is encapsulated by the Future<V> object when the task finishes.
I'll discuss the other version of the submit() method and then return to the question of what you can do
with a Future<V> object.
Executing Callable<V> Tasks
Search WWH ::




Custom Search