Java Reference
In-Depth Information
There are several ways to create a
Future
to describe a task. The
submit
methods in
ExecutorService
all return a
Future
, so that you can submit a
Runnable
or a
Callable
to an executor and get back a
Future
that can be used to retrieve the result or
cancel the task. You can also explicitly instantiate a
FutureTask
for a given
Runnable
or
Callable
. (Because
FutureTask
implements
Runnable
, it can be submitted to an
Executor
for execution or executed directly by calling its
run
method.)
As of Java 6,
ExecutorService
implementations can override
newTaskFor
in
Ab-
stractExecutorService
to control instantiation of the
Future
corresponding to a
submitted
Callable
or
Runnable
. The default implementation just creates a new
Fu-
tureTask
, as shown in
Listing 6.12
.
Listing 6.12. Default Implementation of
newTaskFor
in
ThreadPoolExecutor
.
Submitting a
Runnable
or
Callable
to an
Executor
constitutes a safe publication (see
will eventually execute the task. Similarly, setting the result value for a
Future
constitutes
a safe publication of the result from the thread in which it was computed to any thread that
retrieves it via
get
.
6.3.3. Example: Page Renderer with Future
As a first step towards making the page renderer more concurrent, let's divide it into two
tasks, one that renders the text and one that downloads all the images. (Because one task
is largely CPU-bound and the other is largely I/O-bound, this approach may yield improve-
ments even on single-CPU systems.)
Callable
and
Future
can help us express the interaction between these cooperating
images, and submit it to an
ExecutorService
. This returns a
Future
describing the
task's execution; when the main task gets to the point where it needs the images, it waits for
the result by calling
Future.get
. Ifwe're lucky, the results will already be ready by the
time we ask; otherwise, at least we got a head start on downloading the images.