クラス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を返します。

使用例。 ここでは、指定されたlong[]配列をソートする簡単だが完全なForkJoinソートを示します。

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);
    }
  }
  // implementation details follow:
  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));
    }
  }
}

次の例は、パフォーマンスを向上させる可能性のある調整や方法のいくつかを示しています。RecursiveActionは、基本的な分割統治法を維持しているかぎり、完全に再帰的である必要はありません。 ここでは、繰返し除算の右辺のみを2で分割し、それらをnext参照のチェーンで追跡することによってdouble配列の各要素の2乗を合計するクラスを示します。 これは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; // keeps track of right-hand-side tasks
  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) // perform leftmost base step
      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()) // directly calculate if not stolen
        sum += right.atLeaf(right.lo, right.hi);
      else {
        right.join();
        sum += right.result;
      }
      right = right.next;
    }
    result = sum;
  }
}

導入されたバージョン:
1.7
関連項目:
  • コンストラクタの詳細

    • RecursiveAction

      public RecursiveAction()
      サブクラスが呼び出すためのコンストラクタ。
  • メソッドの詳細

    • compute

      protected abstract void compute()
      このタスクによって実行される主な計算です。
    • getRawResult

      public final Void getRawResult()
      常にnullを返します。
      定義:
      getRawResult、クラスForkJoinTask<Void>
      戻り値:
      null (常時)
    • setRawResult

      protected final void setRawResult(Void mustBeNull)
      null完了値が必要です。
      定義:
      setRawResult、クラスForkJoinTask<Void>
      パラメータ:
      mustBeNull - 値
    • exec

      protected final boolean exec()
      RecursiveActionsのための実行規則を実装します。
      定義:
      exec、クラスForkJoinTask<Void>
      戻り値:
      このタスクが正常に完了したことがわかっている場合はtrue