jsr166y.forkjoin
public abstract class RecursiveAction extends ForkJoinTask<java.lang.Void>
class SortTask extends RecursiveAction { final long[] array; final int lo; final int hi; SortTask(long[] array, int lo, int hi) { this.array = array; this.lo = lo; this.hi = hi; } protected void compute() { if (hi - lo < THRESHOLD) sequentiallySort(array, lo, hi); else { int mid = (lo + hi) >>> 1; forkJoin(new SortTask(array, lo, mid), new SortTask(array, mid, hi)); merge(array, lo, hi); } } }You could then sort anArray by creating new SortTask(anArray, 0, anArray.length-1) and invoking it in a ForkJoinPool. As a more concrete simple example, the following task increments each element of an array:
class IncrementTask extends RecursiveAction { final long[] array; final int lo; final int hi; IncrementTask(long[] array, int lo, int hi) { this.array = array; this.lo = lo; this.hi = hi; } protected void compute() { if (hi - lo < THRESHOLD) { for (int i = lo; i < hi; ++i) array[i]++; } else { int mid = (lo + hi) >>> 1; forkJoin(new IncrementTask(array, lo, mid), new IncrementTask(array, mid, hi)); } } }
RecursiveActions need not be fully recursive, so long as they maintain the basic divide-and-conquer approach. For example, here is a class that sums the squares of each element of a double array, by subdividing out only the right-hand-sides of repeated divisions by two, and keeping track of them with a chain of next references. It uses a common rule of thumb for granularity settings, corresponding to about eight times as many base tasks as there are threads in the pool.
double sumOfSquares(ForkJoinPool pool, double[] array) { int n = array.length; int seqSize = 1 + n / (8 * pool.getParallelismLevel()); Applyer a = new Applyer(array, 0, n-1, seqSize, null); pool.invoke(a); return a.result; } class Applyer extends RecursiveAction { final double[] array; final int lo, hi, seqSize; int result; Applyer next; // keeps track of right-hand-side tasks Applyer(double[] array, int lo, int hi, int seqSize, Applyer next) { this.array = array; this.lo = lo; this.hi = hi; this.seqSize = seqSize; this.next = next; } protected void compute() { int l = lo; int h = hi; Applyer right = null; while (h - l > seqSize) { // fork right-hand sides int mid = (l + h) >>> 1; right = new Applyer(array, mid, h, seqSize, right); right.fork(); h = mid; } double sum = 0; for (int i = l; i < h; ++i) // perform leftmost base step sum += array[i] * array[i]; while (right != null) { // join right-hand sides right.join(); sum += right.result; right = right.next; } result = sum; } }
Constructor and Description |
---|
RecursiveAction() |
Modifier and Type | Method and Description |
---|---|
protected abstract void |
compute()
The main computation performed by this task.
|
java.lang.Throwable |
exec()
Immediately commences execution of this task by the current
worker thread unless already cancelled, returning any exception
thrown by its compute method.
|
void |
finish()
Equivalent to finish(null).
|
void |
finish(java.lang.Void result)
Completes this task, and if not already aborted or cancelled,
returning the given result upon join and related
operations.
|
void |
finishExceptionally(java.lang.Throwable ex)
Completes this task abnormally, and if not already aborted or
cancelled, causes it to throw the given exception upon
join and related operations.
|
java.lang.Void |
forkJoin()
Equivalent in effect to the sequence fork(); join();
but may be more efficient.
|
static void |
forkJoin(java.util.List<? extends RecursiveAction> tasks)
Forks all tasks in the list, returning when isDone
holds for all of them.
|
static void |
forkJoin(RecursiveAction[] tasks)
Forks all tasks in the array, returning when isDone
holds for all of them.
|
static void |
forkJoin(RecursiveAction t1,
RecursiveAction t2)
Forks both tasks and returns when isDone holds for
both..
|
java.lang.Void |
rawResult()
Always returns null.
|
cancel, fork, getException, isCancelled, isDone, isStolen, join, quietlyJoin, reinitialize
protected abstract void compute()
public static void forkJoin(RecursiveAction t1, RecursiveAction t2)
java.lang.NullPointerException
- if t1 or t2 are null.public static void forkJoin(RecursiveAction[] tasks)
java.lang.NullPointerException
- if array or any element of array are nullpublic static void forkJoin(java.util.List<? extends RecursiveAction> tasks)
java.lang.NullPointerException
- if list or any element of list are null.public final java.lang.Void rawResult()
rawResult
in class ForkJoinTask<java.lang.Void>
public final java.lang.Void forkJoin()
ForkJoinTask
forkJoin
in class ForkJoinTask<java.lang.Void>
public final java.lang.Throwable exec()
ForkJoinTask
exec
in class ForkJoinTask<java.lang.Void>
public final void finish()
public final void finish(java.lang.Void result)
ForkJoinTask
finish
in class ForkJoinTask<java.lang.Void>
result
- the result to returnpublic final void finishExceptionally(java.lang.Throwable ex)
ForkJoinTask
finishExceptionally
in class ForkJoinTask<java.lang.Void>
ex
- the exception to throw. While not necessarily
statically enforced, this must be a RuntimeException or Error.