New in the Java SE 7 release, the fork/join framework is an implementation of the
ExecutorService interface that helps you take advantage of
multiple processors. It is designed for work that can be broken into smaller pieces recursively. The goal is to use all the available processing power to
enhance the performance of your application.
As with any
ExecutorService, the fork/join framework distributes tasks to worker threads in a thread pool. The fork/join framework is distinct
because it uses a work-stealing algorithm. Worker threads that run out of things to do can steal tasks from other threads that are still busy.
The center of the fork/join framework is the
ForkJoinPool class, an extension of
implements the core work-stealing algorithm and can execute
Using the fork/join framework is simple. The first step is to write some code that performs a segment of the work. Your code should look similar to this:
if (my portion of the work is small enough) do the work directly else split my work into two pieces invoke the two pieces and wait for the results
Wrap this code as a
ForkJoinTask subclass, typically as one of its more specialized types
RecursiveTask (which can return a result)
ForkJoinTask is ready, create one that represents all the work to be done and pass it to the
invoke() method of a
The core Java 7 fork/join addition is a new
ForkJoinPool executor that is dedicated to running instances implementing
ForkJoinTask objects support the creation of subtasks plus waiting for the subtasks to complete. With those clear semantics, the executor is able
to dispatch tasks among its internal threads pool by "stealing" jobs when a task is waiting for another task to complete and there are pending tasks to be run.
ForkJoinTask objects feature two specific methods:
fork() method allows a
ForkJoinTask to be planned for asynchronous execution. This allows a new
ForkJoinTask to be launched from an existing one.
In turn, the
join() method allows a
ForkJoinTask to wait for the completion of another one.
Cooperation among tasks happens through
join(), as illustrated in figure below. Note that the
join() method names should not be confused with their POSIX counterparts with which a process can
duplicate itself. There,
fork() only schedules a new task within a
ForkJoinPool, but no child Java Virtual
Machine is ever created.
There are two types of
RecursiveAction represent executions that do not yield a return value.
In contrast, instances of
RecursiveTask yield return values.
RecursiveTask is preferred because most divide-and-conquer algorithms return a value from a computation over
a data set. For the execution of tasks, different synchronous and asynchronous options are provided, making it possible to implement