Java Reference
In-Depth Information
Here, you generate an array containing the first n natural numbers using a LongStream. Then
you create a ForkJoinTask (the superclass of RecursiveTask), passing this array to the public
constructor of the ForkJoinSumCalculator shown in listing 7.2 . Finally, you create a new
ForkJoinPool and pass that task to its invoke method. The value returned by this last method is
the result of the task defined by the Fork-JoinSumCalculator class when executed inside the
ForkJoinPool.
Note that in a real-world application, it doesn't make sense to use more than one ForkJoinPool.
For this reason, what you typically should do is instantiate it only once and keep this instance in
a static field, making it a singleton, so it could be conveniently reused by any part of your
software. Here, to create it you're using its default no-argument constructor, meaning that you
want to allow the pool to use all the processors available to the JVM. More precisely, this
constructor will use the value returned by Runtime.availableProcessors to determine the
number of threads used by the pool. Note that the availableProcessors method, despite its name,
in reality returns the number of available cores, including any virtual ones due to
hyperthreading.
Running the ForkJoinSumCalculator
When you pass the ForkJoinSumCalculator task to the ForkJoinPool, this task is executed by a
thread of the pool that in turn calls the compute method of the task. This method checks to see if
the task is small enough to be performed sequentially; otherwise, it splits the array of numbers
to be summed into two halves and assigns them to two new ForkJoinSumCalculators that are
scheduled to be executed by the ForkJoinPool. As a result, this process can be recursively
repeated, allowing the original task to be divided into smaller tasks, until the condition used to
check if it's no longer convenient or no longer possible to further split it is met (in this case, if
the number of items to be summed is less than or equal to 10,000). At this point, the result of
each subtask is computed sequentially, and the (implicit) binary tree of tasks created by the
forking process is traversed back toward its root. The result of the task is then computed,
combining the partial results of each subtask. This process is shown in figure 7.4 .
 
Search WWH ::




Custom Search