Module java.base

Class RecursiveAction

java.lang.Object
java.util.concurrent.ForkJoinTask<Void>
java.util.concurrent.RecursiveAction
所有已实现的接口:
Serializable, Future<Void>

public abstract class RecursiveAction extends ForkJoinTask<Void>
一个递归的无结果ForkJoinTask。这个类建立了将无结果操作参数化为Void ForkJoinTask的约定。因为nullVoid类型的唯一有效值,所以诸如join等方法在完成后总是返回null

示例用法。 这里是一个简单但完整的ForkJoin排序,用于对给定的long[]数组进行排序:

 
 static class SortTask extends RecursiveAction {
   final long[] array; final int lo, hi;
   SortTask(long[] array, int lo, int hi) {
     this.array = array; this.lo = lo; this.hi = hi;
   }
   SortTask(long[] array) { this(array, 0, array.length); }
   protected void compute() {
     if (hi - lo < THRESHOLD)
       sortSequentially(lo, hi);
     else {
       int mid = (lo + hi) >>> 1;
       invokeAll(new SortTask(array, lo, mid),
                 new SortTask(array, mid, hi));
       merge(lo, mid, hi);
     }
   }
   // 实现细节如下:
   static final int THRESHOLD = 1000;
   void sortSequentially(int lo, int hi) {
     Arrays.sort(array, lo, hi);
   }
   void merge(int lo, int mid, int hi) {
     long[] buf = Arrays.copyOfRange(array, lo, mid);
     for (int i = 0, j = lo, k = mid; i < buf.length; j++)
       array[j] = (k == hi || buf[i] < array[k]) ?
         buf[i++] : array[k++];
   }
 }
然后,通过创建new SortTask(anArray)并在ForkJoinPool中调用它来对anArray进行排序。作为一个更具体的简单示例,以下任务递增数组的每个元素:
 
 class IncrementTask extends RecursiveAction {
   final long[] array; final int lo, 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;
       invokeAll(new IncrementTask(array, lo, mid),
                 new IncrementTask(array, mid, hi));
     }
   }
 }

以下示例说明了一些可能导致更好性能的改进和习惯用法:RecursiveActions不必完全递归,只要它们保持基本的分治方法即可。这是一个类,它对双精度数组的每个元素的平方求和,通过仅将重复除以二的右侧子分区划分出来,并使用一系列next引用来跟踪它们。它使用基于方法getSurplusQueuedTaskCount的动态阈值,但通过直接在未被窃取的任务上执行叶动作而不进一步细分来抵消潜在的过度分区。

 
 double sumOfSquares(ForkJoinPool pool, double[] array) {
   int n = array.length;
   Applyer a = new Applyer(array, 0, n, null);
   pool.invoke(a);
   return a.result;
 }

 class Applyer extends RecursiveAction {
   final double[] array;
   final int lo, hi;
   double result;
   Applyer next; // 用于跟踪右侧任务
   Applyer(double[] array, int lo, int hi, Applyer next) {
     this.array = array; this.lo = lo; this.hi = hi;
     this.next = next;
   }

   double atLeaf(int l, int h) {
     double sum = 0;
     for (int i = l; i < h; ++i) // 执行最左侧的基本步骤
       sum += array[i] * array[i];
     return sum;
   }

   protected void compute() {
     int l = lo;
     int h = hi;
     Applyer right = null;
     while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
       int mid = (l + h) >>> 1;
       right = new Applyer(array, mid, h, right);
       right.fork();
       h = mid;
     }
     double sum = atLeaf(l, h);
     while (right != null) {
       if (right.tryUnfork()) // 如果未被窃取,则直接计算
         sum += right.atLeaf(right.lo, right.hi);
       else {
         right.join();
         sum += right.result;
       }
       right = right.next;
     }
     result = sum;
   }
 }
自从:
1.7
参见:
  • Constructor Details

    • RecursiveAction

      public RecursiveAction()
      子类调用的构造函数。
  • Method Details

    • compute

      protected abstract void compute()
      该任务执行的主要计算。
    • getRawResult

      public final Void getRawResult()
      总是返回null
      指定者:
      getRawResult 在类 ForkJoinTask<Void>
      返回:
      总是null
    • setRawResult

      protected final void setRawResult(Void mustBeNull)
      需要空完成值。
      指定者:
      setRawResult 在类 ForkJoinTask<Void>
      参数:
      mustBeNull - 值
    • exec

      protected final boolean exec()
      为RecursiveActions实现执行约定。
      指定者:
      exec 在类 ForkJoinTask<Void>
      返回:
      如果此任务已知正常完成,则返回true