Spec-Zone.ru › OpenJDK 25

Класс 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 ForkJoinTasks. Поскольку null — единственное допустимое значение типа Void, такие методы, как 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);
    }
  }
  // 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++];
  }
}
Затем можно отсортировать anArray, создав new SortTask(anArray) и вызвав её в ForkJoinPool. В качестве более конкретного простого примера следующая задача увеличивает каждый элемент массива на единицу:
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 не обязательно должны быть полностью рекурсивными, если они придерживаются основного подхода «разделяй и властвуй». Ниже приведён класс, который вычисляет сумму квадратов элементов массива double, разбивая только правые части последовательных делений пополам и сохраняя их с помощью цепочки ссылок 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; // 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
См. также:
  • Сериализованная форма

Краткое описание вложенных классов

Вложенные классы/интерфейсы, объявленные в интерфейсе Future

Future.State

Краткое описание конструкторов

Конструктор Описание
RecursiveAction()
Конструктор, вызываемый подклассами.

Краткое описание методов

Модификатор и тип Метод Описание
protected abstract void compute()
Основное вычисление, выполняемое этой задачей.
protected final boolean exec()
Реализует соглашения о выполнении для RecursiveAction.
final Void getRawResult()
Всегда возвращает null.
protected final void setRawResult(Void mustBeNull)
Требует null в качестве значения завершения.

Методы, объявленные в классе ForkJoinTask

adapt, adapt, adapt, adaptInterruptible, adaptInterruptible, adaptInterruptible, cancel, compareAndSetForkJoinTaskTag, complete, completeExceptionally, exceptionNow, fork, get, get, getException, getForkJoinTaskTag, getPool, getQueuedTaskCount, getSurplusQueuedTaskCount, helpQuiesce, inForkJoinPool, invoke, invokeAll, invokeAll, invokeAll, isCancelled, isCompletedAbnormally, isCompletedNormally, isDone, join, peekNextLocalTask, pollNextLocalTask, pollSubmission, pollTask, quietlyComplete, quietlyInvoke, quietlyJoin, quietlyJoin, quietlyJoinUninterruptibly, reinitialize, resultNow, setForkJoinTaskTag, state, tryUnfork

Методы, объявленные в классе Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Подробное описание конструкторов

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()
Реализует соглашения о выполнении для RecursiveAction.
Определено в:
exec в классе ForkJoinTask<Void>
Возвращает:
true, если известно, что эта задача завершилась нормально

Сообщить об ошибке или предложить улучшение
Дополнительные справочные материалы по API и документацию для разработчиков см. в разделе Документация Java SE, содержащем более подробные описания для разработчиков, концептуальные обзоры, определения терминов, обходные решения и рабочие примеры кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или её дочерних компаний в США и других странах.
Авторское право © 1993, 2025, Oracle и/или её дочерние компании, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/concurrent/RecursiveAction.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API