Java Reference
In-Depth Information
private int getArea() { return (endRow
- startRow) * (endCol - startCol); }
}
How It Works
The
Fork
/
Join
framework can be used for breaking down tasks into discrete units of
work. The first part of the solution creates a
ForkJoinPool
object. The default con-
structor provides reasonable defaults (such as creating as many threads as there are
CPU cores) and sets up an entry point to submit divide-and-conquer work. While the
ForkJoinPool
inherits from
ExecutorService
, it is best suited to handle tasks
that extend from
RecursiveAction
. The
ForkJoinPool
object has the
in-
voke(RecursiveAction)
method, which will take a
RecursiveAction
ob-
ject and apply the divide-and-conquer strategy.
The second part of the solution creates the
GameOfLifeAdvancer
class, which
extends the
RecursiveAction
class. By extending the
RecursiveAction
class,
the work can be split. The
GameOfLifeAdvancer
class advances the Game of Life
board to the next generation. The constructor takes a two-dimensional Boolean array
(which represents a Game of Life board), a start row/column, an end row/column, and
a destination two-dimensional Boolean array, on which the result of advancing the
Game of Life for one generation is collected.
The
GameOfLifeAdvancer
is required to implement the
compute()
method.
In this method, determine how much work there is to be completed. If the work is
small enough, the work is completed directly (achieved by calling the
computeDir-
ectly()
method and returning). If the work is not small enough, the method splits
the work by creating two
GameOfLifeAdvancer
instances that process only half of
the current
GameOfLifeAdvancer
work. This is done by either splitting the num-
ber of rows to be processed into two chunks or by splitting the number of columns into
two chunks. The two
GameOfLifeAdvancer
instances are then passed to the
ForkJoin
pool by calling the
invokeAll()
method of the
RecursiveAction
class. The
invokeAll()
method takes the two instances of
GameOfLifeAdvan-
cer
(it can take as many as needed) and waits until they both are finished executing
(that is, the meaning of the
-all
postfix in the
invokeAll()
method name; it waits
for all of the tasks submitted to be completed before returning control).