jsr166z.forkjoin
Class RecursiveAction

java.lang.Object
  extended by jsr166z.forkjoin.ForkJoinTask<java.lang.Void>
      extended by jsr166z.forkjoin.RecursiveAction

public abstract class RecursiveAction
extends ForkJoinTask<java.lang.Void>

Recursive resultless ForkJoinTasks. To maintain conformance with other classes in this framework, RecursiveActions are parameterized as Void ForkJoinTasks, and return null as results. But for simplicity and efficiency, the compute method and related methods use void. RecursiveActions normally proceed via parallel divide and conquer; very often using the convenient (and typically more efficient) combined method coInvoke. Here is a sketch of a ForkJoin sort that sorts a given long[] array:

 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;
       coInvoke(new SortTask(array, lo, mid),
                new SortTask(array, mid+1, hi));
       merge(array, lo, hi);
     }
     return null;
   }
 }
 
You could then sort anArray by creating new SortTask(anArray, 0, anArray.length-1) and invoking it in a ForkJoinPool.

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+1, 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 Summary
RecursiveAction()
           
 
Method Summary
static void coInvoke(java.util.List<? extends RecursiveAction> tasks)
          Forks all tasks in the list, returning when isDone holds for all of them.
static void coInvoke(RecursiveAction[] tasks)
          Forks all tasks in the array, returning when isDone holds for all of them.
static void coInvoke(RecursiveAction t1, RecursiveAction t2)
          Forks both tasks and returns when isDone holds for both..
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 invoke()
          Equivalent in effect to the sequence fork(); join(); but may be more efficient.
 java.lang.Void rawResult()
          Always returns null.
 
Methods inherited from class jsr166z.forkjoin.ForkJoinTask
cancel, fork, getException, isCancelled, isDone, isStolen, join, quietlyJoin, reinitialize
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

RecursiveAction

public RecursiveAction()
Method Detail

compute

protected abstract void compute()
The main computation performed by this task. While you must define this method, you should not in general call it directly. To immediately perform the computation, use invoke.


coInvoke

public static void coInvoke(RecursiveAction t1,
                            RecursiveAction t2)
Forks both tasks and returns when isDone holds for both.. If both tasks encounter exceptions, only one of them (arbitrarily chosen) is thrown from this method. You can check individual status using method getException. This method may be invoked only from within other ForkJoinTask computations. Attempts to invoke in other contexts result in exceptions or errors including ClassCastException.

Throws:
java.lang.NullPointerException - if t1 or t2 are null.

coInvoke

public static void coInvoke(RecursiveAction[] tasks)
Forks all tasks in the array, returning when isDone holds for all of them. If any task encounters an exception, others are cancelled. This method may be invoked only from within other ForkJoinTask computations. Attempts to invoke in other contexts result in exceptions or errors including ClassCastException.

Throws:
java.lang.NullPointerException - if array or any element of array are null

coInvoke

public static void coInvoke(java.util.List<? extends RecursiveAction> tasks)
Forks all tasks in the list, returning when isDone holds for all of them. If any task encounters an exception, others are cancelled. This method may be invoked only from within other ForkJoinTask computations. Attempts to invoke in other contexts result in exceptions or errors including ClassCastException.

Throws:
java.lang.NullPointerException - if list or any element of list are null.

rawResult

public final java.lang.Void rawResult()
Always returns null.

Specified by:
rawResult in class ForkJoinTask<java.lang.Void>
Returns:
null

invoke

public final java.lang.Void invoke()
Description copied from class: ForkJoinTask
Equivalent in effect to the sequence fork(); join(); but may be more efficient.

Specified by:
invoke in class ForkJoinTask<java.lang.Void>
Returns:
the computed result

exec

public final java.lang.Throwable exec()
Description copied from class: ForkJoinTask
Immediately commences execution of this task by the current worker thread unless already cancelled, returning any exception thrown by its compute method.

Specified by:
exec in class ForkJoinTask<java.lang.Void>
Returns:
exception thrown by compute (or via cancellation), or null if none

finish

public final void finish()
Equivalent to finish(null).


finish

public final void finish(java.lang.Void result)
Description copied from class: ForkJoinTask
Completes this task, and if not already aborted or cancelled, returning the given result upon join and related operations.

Specified by:
finish in class ForkJoinTask<java.lang.Void>
Parameters:
result - the result to return

finishExceptionally

public final void finishExceptionally(java.lang.Throwable ex)
Description copied from class: ForkJoinTask
Completes this task abnormally, and if not already aborted or cancelled, causes it to throw the given exception upon join and related operations.

Specified by:
finishExceptionally in class ForkJoinTask<java.lang.Void>
Parameters:
ex - the exception to throw. While not necessarily statically enforced, this must be a RuntimeException or Error.