Spec-Zone.ru › OpenJDK 27

Класс CountedCompleter<T>

java.lang.Object
java.util.concurrent.ForkJoinTask<T>
java.util.concurrent.CountedCompleter<T>
Параметры типа:
T - тип результата завершающего объекта
Все реализуемые интерфейсы:
Serializable, Future<T>
public abstract class CountedCompleter<T> extends ForkJoinTask<T>
ForkJoinTask с действием завершения, выполняемым при срабатывании, когда не остается ожидающих действий. CountedCompleter обычно более устойчивы к задержкам и блокировкам подзадач, чем другие разновидности ForkJoinTask, но менее интуитивны в программировании. CountedCompleter используются аналогично другим компонентам, основанным на завершении (например, CompletionHandler), за исключением того, что для запуска действия завершения onCompletion(CountedCompleter) может потребоваться несколько ожидающих завершений, а не одно. Если не задано иное, счетчик ожидающих действий изначально равен нулю, но его можно (атомарно) изменить с помощью методов setPendingCount(int), addToPendingCount(int) и compareAndSetPendingCount(int, int). При вызове tryComplete(), если счетчик ожидающих действий не равен нулю, он уменьшается; в противном случае выполняется действие завершения, и, если у этого завершающего объекта есть собственный завершающий объект, процесс продолжается с ним. Как и в случае связанных компонентов синхронизации, таких как Phaser и Semaphore, эти методы влияют только на внутренние счетчики; они не ведут никакого дополнительного внутреннего учета. В частности, идентификаторы ожидающих задач не сохраняются. Как показано ниже, при необходимости можно создавать подклассы, которые регистрируют некоторые или все ожидающие задачи либо их результаты. Ниже также показаны вспомогательные методы, позволяющие настраивать обходы завершения. Однако, поскольку CountedCompleter предоставляют только базовые механизмы синхронизации, может быть полезно создать дополнительные абстрактные подклассы, поддерживающие связи, поля и дополнительные методы, необходимые для набора связанных вариантов использования.

Конкретный класс CountedCompleter должен определять метод compute(), который в большинстве случаев (как показано ниже) должен вызывать tryComplete() один раз перед возвратом. Класс также может переопределить метод onCompletion(CountedCompleter) для выполнения действия при штатном завершении и метод onExceptionalCompletion(Throwable, CountedCompleter) для выполнения действия при возникновении любого исключения.

Чаще всего CountedCompleter не возвращают результаты; в этом случае их обычно объявляют как CountedCompleter<Void>, и в качестве значения результата они всегда возвращают null. В других случаях следует переопределить метод getRawResult(), чтобы предоставить результат из join(), invoke() и связанных методов. Как правило, этот метод должен возвращать значение поля (или результат функции от одного или нескольких полей) объекта CountedCompleter, в котором хранится результат после завершения. Метод setRawResult(T) по умолчанию не играет роли в CountedCompleter. Можно, хотя это редко бывает целесообразно, переопределить этот метод для поддержки других объектов или полей, хранящих данные результата.

CountedCompleter, у которого самого нет завершающего объекта (то есть для которого getCompleter() возвращает null), можно использовать как обычный ForkJoinTask с дополнительной функциональностью. Однако любой завершающий объект, у которого, в свою очередь, есть другой завершающий объект, служит только внутренним вспомогательным элементом для других вычислений, поэтому состояние его собственной задачи (отражаемое такими методами, как ForkJoinTask.isDone()) произвольно; оно меняется только при явных вызовах complete(T), ForkJoinTask.cancel(boolean), ForkJoinTask.completeExceptionally(Throwable) или при исключительном завершении метода compute. При любом исключительном завершении исключение может быть передано завершающему объекту задачи (и далее по цепочке), если такой объект существует и еще не завершился иным образом. Аналогично, отмена внутреннего CountedCompleter влияет только на этот завершающий объект и поэтому обычно бесполезна.

Примеры использования.

Параллельная рекурсивная декомпозиция. CountedCompleter можно организовать в деревья, подобные тем, которые часто используются с RecursiveAction, хотя способы их построения обычно различаются. Здесь завершающим объектом каждой задачи является ее родитель в дереве вычислений. Несмотря на то, что для них требуется немного больше учета, CountedCompleter могут быть предпочтительнее при применении потенциально длительной операции (которую нельзя дополнительно разбить) к каждому элементу массива или коллекции; особенно если для некоторых элементов выполнение операции занимает значительно больше времени, чем для других, из-за естественных различий (например, ввода-вывода) или побочных факторов, таких как сборка мусора. Поскольку CountedCompleter предоставляют собственные продолжения, другим задачам не нужно блокироваться в ожидании их выполнения.

Например, ниже приведена начальная версия вспомогательного метода, который использует рекурсивную декомпозицию с делением пополам, чтобы разбить работу на отдельные части (конечные задачи). Даже если работа разделена на отдельные вызовы, методы на основе деревьев обычно предпочтительнее непосредственного порождения конечных задач, поскольку они сокращают обмен данными между потоками и улучшают балансировку нагрузки. В рекурсивном случае вторая из каждой пары завершающихся подзадач запускает завершение родителя (поскольку объединение результатов не выполняется, реализация метода onCompletion по умолчанию, ничего не делающая, не переопределяется). Вспомогательный метод создает корневую задачу и вызывает ее (здесь неявно используется ForkJoinPool.commonPool()). Просто и надежно (но не оптимально) всегда устанавливать счетчик ожидающих действий в число дочерних задач и вызывать tryComplete() непосредственно перед возвратом.

public static <E> void forEach(E[] array, Consumer<E> action) {
  class Task extends CountedCompleter<Void> {
    final int lo, hi;
    Task(Task parent, int lo, int hi) {
      super(parent); this.lo = lo; this.hi = hi;
    }

    public void compute() {
      if (hi - lo >= 2) {
        int mid = (lo + hi) >>> 1;
        // must set pending count before fork
        setPendingCount(2);
        new Task(this, mid, hi).fork(); // right child
        new Task(this, lo, mid).fork(); // left child
      }
      else if (hi > lo)
        action.accept(array[lo]);
      tryComplete();
    }
  }
  new Task(null, 0, array.length).invoke();
}
Эту схему можно улучшить, заметив, что в рекурсивном случае после порождения правой задачи самой задаче больше нечего делать, поэтому перед возвратом она может напрямую вызвать левую задачу. (Это аналог устранения хвостовой рекурсии.) Кроме того, когда последнее действие задачи — породить или вызвать подзадачу («хвостовой вызов»), вызов tryComplete() можно оптимизировать, но тогда счетчик ожидающих действий будет иметь значение на единицу меньше ожидаемого.
    public void compute() {
      if (hi - lo >= 2) {
        int mid = (lo + hi) >>> 1;
        setPendingCount(1); // looks off by one, but correct!
        new Task(this, mid, hi).fork(); // right child
        new Task(this, lo, mid).compute(); // direct invoke
      } else {
        if (hi > lo)
          action.accept(array[lo]);
        tryComplete();
      }
    }
В качестве дополнительной оптимизации заметим, что левая задача вообще не обязательна. Вместо создания новой задачи можно продолжить использовать исходную и увеличивать счетчик ожидающих действий для каждого порождения задачи. Кроме того, поскольку ни одна задача в этом дереве не реализует метод onCompletion(CountedCompleter), tryComplete можно заменить на propagateCompletion().
    public void compute() {
      int n = hi - lo;
      for (; n >= 2; n /= 2) {
        addToPendingCount(1);
        new Task(this, lo + n/2, lo + n).fork();
      }
      if (n > 0)
        action.accept(array[lo]);
      propagateCompletion();
    }
Если счетчики ожидающих действий можно вычислить заранее, их можно задать в конструкторе:
public static <E> void forEach(E[] array, Consumer<E> action) {
  class Task extends CountedCompleter<Void> {
    final int lo, hi;
    Task(Task parent, int lo, int hi) {
      super(parent, 31 - Integer.numberOfLeadingZeros(hi - lo));
      this.lo = lo; this.hi = hi;
    }

    public void compute() {
      for (int n = hi - lo; n >= 2; n /= 2)
        new Task(this, lo + n/2, lo + n).fork();
      action.accept(array[lo]);
      propagateCompletion();
    }
  }
  if (array.length > 0)
    new Task(null, 0, array.length).invoke();
}
К дополнительным оптимизациям таких классов могут относиться создание специализированных классов для конечных шагов, разбиение, например, на четыре части вместо двух за итерацию и использование адаптивного порога вместо постоянного деления до отдельных элементов.

Поиск. Дерево CountedCompleter может выполнять поиск значения или свойства в разных частях структуры данных и сообщать результат в AtomicReference, как только результат найден. Остальные задачи могут проверять этот результат, чтобы избежать ненужной работы. (Можно также отменить другие задачи, но обычно проще и эффективнее позволить им обнаружить, что результат установлен, и пропустить дальнейшую обработку.) Снова покажем это на примере массива с полным разбиением (на практике конечные задачи почти всегда обрабатывают более одного элемента):

class Searcher<E> extends CountedCompleter<E> {
  final E[] array; final AtomicReference<E> result; final int lo, hi;
  Searcher(CountedCompleter<?> p, E[] array, AtomicReference<E> result, int lo, int hi) {
    super(p);
    this.array = array; this.result = result; this.lo = lo; this.hi = hi;
  }
  public E getRawResult() { return result.get(); }
  public void compute() { // similar to ForEach version 3
    int l = lo, h = hi;
    while (result.get() == null && h >= l) {
      if (h - l >= 2) {
        int mid = (l + h) >>> 1;
        addToPendingCount(1);
        new Searcher(this, array, result, mid, h).fork();
        h = mid;
      }
      else {
        E x = array[l];
        if (matches(x) && result.compareAndSet(null, x))
          quietlyCompleteRoot(); // root task is now joinable
        break;
      }
    }
    tryComplete(); // normally complete whether or not found
  }
  boolean matches(E e) { ... } // return true if found

  public static <E> E search(E[] array) {
      return new Searcher<E>(null, array, new AtomicReference<E>(), 0, array.length).invoke();
  }
}
В этом примере, а также в других случаях, когда задачи не имеют иных побочных эффектов, кроме как compareAndSet общий результат, завершающий безусловный вызов tryComplete можно сделать условным (if (result.get() == null) tryComplete();), поскольку после завершения корневой задачи для управления завершением больше не требуется дополнительный учет.

Регистрация подзадач. Задачам CountedCompleter, объединяющим результаты нескольких подзадач, обычно требуется доступ к этим результатам в методе onCompletion(CountedCompleter). Как показано в следующем классе (реализующем упрощенную разновидность map-reduce, где отображения и редукции имеют тип E), один из способов сделать это в схемах «разделяй и властвуй» — поручить каждой подзадаче сохранять ссылку на соседнюю задачу, чтобы к ней можно было обратиться в методе onCompletion. Этот прием подходит для редукций, в которых порядок объединения левого и правого результатов не имеет значения; для упорядоченных редукций необходимо явно обозначать левую и правую стороны. Могут также применяться варианты других упрощений, рассмотренных в предыдущих примерах.

class MyMapper<E> { E apply(E v) {  ...  } }
class MyReducer<E> { E apply(E x, E y) {  ...  } }
class MapReducer<E> extends CountedCompleter<E> {
  final E[] array; final MyMapper<E> mapper;
  final MyReducer<E> reducer; final int lo, hi;
  MapReducer<E> sibling;
  E result;
  MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
             MyReducer<E> reducer, int lo, int hi) {
    super(p);
    this.array = array; this.mapper = mapper;
    this.reducer = reducer; this.lo = lo; this.hi = hi;
  }
  public void compute() {
    if (hi - lo >= 2) {
      int mid = (lo + hi) >>> 1;
      MapReducer<E> left = new MapReducer(this, array, mapper, reducer, lo, mid);
      MapReducer<E> right = new MapReducer(this, array, mapper, reducer, mid, hi);
      left.sibling = right;
      right.sibling = left;
      setPendingCount(1); // only right is pending
      right.fork();
      left.compute();     // directly execute left
    }
    else {
      if (hi > lo)
          result = mapper.apply(array[lo]);
      tryComplete();
    }
  }
  public void onCompletion(CountedCompleter<?> caller) {
    if (caller != this) {
      MapReducer<E> child = (MapReducer<E>)caller;
      MapReducer<E> sib = child.sibling;
      if (sib == null || sib.result == null)
        result = child.result;
      else
        result = reducer.apply(child.result, sib.result);
    }
  }
  public E getRawResult() { return result; }

  public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
    return new MapReducer<E>(null, array, mapper, reducer,
                             0, array.length).invoke();
  }
}
Здесь метод onCompletion имеет форму, типичную для многих схем завершения, объединяющих результаты. Этот метод обратного вызова вызывается один раз для каждой задачи в одном из двух случаев, когда счетчик ожидающих действий равен нулю или становится равен нулю: (1) самой задачей, если ее счетчик ожидающих действий равен нулю при вызове tryComplete, или (2) любой из ее подзадач, когда они завершаются и уменьшают счетчик ожидающих действий до нуля. Аргумент caller позволяет различить эти случаи. Чаще всего, если вызывающий объект — this, никаких действий не требуется. В противном случае аргумент вызывающего объекта можно использовать (обычно с помощью приведения типа), чтобы передать значение (и/или ссылки на другие значения) для объединения. При правильном использовании счетчиков ожидающих действий действия внутри onCompletion выполняются один раз при завершении задачи и ее подзадач. Для обеспечения потокобезопасного доступа к полям этой задачи или других завершенных задач в рамках этого метода дополнительная синхронизация не требуется.

Обходы завершения. Если использование onCompletion для обработки завершений неприменимо или неудобно, можно использовать методы firstComplete() и nextComplete() для создания пользовательских обходов. Например, чтобы определить MapReducer, который порождает только задачи для правых частей, как в третьем примере ForEach, завершения должны совместно выполнять редукцию по ссылкам на незавершенные подзадачи, что можно сделать следующим образом:

class MapReducer<E> extends CountedCompleter<E> { // version 2
  final E[] array; final MyMapper<E> mapper;
  final MyReducer<E> reducer; final int lo, hi;
  MapReducer<E> forks, next; // record subtask forks in list
  E result;
  MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
             MyReducer<E> reducer, int lo, int hi, MapReducer<E> next) {
    super(p);
    this.array = array; this.mapper = mapper;
    this.reducer = reducer; this.lo = lo; this.hi = hi;
    this.next = next;
  }
  public void compute() {
    int l = lo, h = hi;
    while (h - l >= 2) {
      int mid = (l + h) >>> 1;
      addToPendingCount(1);
      (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork();
      h = mid;
    }
    if (h > l)
      result = mapper.apply(array[l]);
    // process completions by reducing along and advancing subtask links
    for (CountedCompleter<?> c = firstComplete(); c != null; c = c.nextComplete()) {
      for (MapReducer t = (MapReducer)c, s = t.forks; s != null; s = t.forks = s.next)
        t.result = reducer.apply(t.result, s.result);
    }
  }
  public E getRawResult() { return result; }

  public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
    return new MapReducer<E>(null, array, mapper, reducer,
                             0, array.length, null).invoke();
  }
}

Триггеры. Некоторые CountedCompleter никогда не порождаются сами, а служат связующими элементами в других схемах; в том числе в тех, где завершение одной или нескольких асинхронных задач запускает другую асинхронную задачу. Например:

class HeaderBuilder extends CountedCompleter<...> { ... }
class BodyBuilder extends CountedCompleter<...> { ... }
class PacketSender extends CountedCompleter<...> {
  PacketSender(...) { super(null, 1); ... } // trigger on second completion
  public void compute() { } // never called
  public void onCompletion(CountedCompleter<?> caller) { sendPacket(); }
}
// sample use:
PacketSender p = new PacketSender();
new HeaderBuilder(p, ...).fork();
new BodyBuilder(p, ...).fork();
С версии:
1.8
См. также:
  • Сериализованная форма

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

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

Future.State
Модификатор и тип Интерфейс Описание
static enum  Future.State
Представляет состояние вычисления.

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

CountedCompleter()
CountedCompleter(CountedCompleter<?> completer)
CountedCompleter(CountedCompleter<?> completer, int initialPendingCount)
Модификатор Конструктор Описание
protected
Создает новый CountedCompleter без завершающей задачи и с начальным счетчиком ожидающих задач, равным нулю.
protected
Создает новый CountedCompleter с указанной завершающей задачей и начальным счетчиком ожидающих задач, равным нулю.
protected
Создает новый CountedCompleter с указанной завершающей задачей и начальным счетчиком ожидающих задач.

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

Модификатор и тип Метод Описание
final void addToPendingCount(int delta)
Атомарно добавляет указанное значение к счетчику ожидающих задач.
final boolean compareAndSetPendingCount(int expected, int count)
Атомарно устанавливает счетчик ожидающих задач в указанное значение, только если в данный момент он содержит ожидаемое значение.
void complete(T rawResult)
Независимо от счетчика ожидающих задач вызывает onCompletion(CountedCompleter), помечает эту задачу как завершенную и дополнительно вызывает tryComplete() для завершающей задачи этой задачи, если она существует.
abstract void compute()
Основное вычисление, выполняемое этой задачей.
final int decrementPendingCountUnlessZero()
Если счетчик ожидающих задач не равен нулю, атомарно уменьшает его.
protected final boolean exec()
Реализует соглашения о выполнении для CountedCompleter.
final CountedCompleter<?> firstComplete()
Если счетчик ожидающих задач этой задачи равен нулю, возвращает эту задачу; в противном случае уменьшает ее счетчик ожидающих задач и возвращает null.
final CountedCompleter<?> getCompleter()
Возвращает завершающую задачу, заданную в конструкторе этой задачи, или null, если ее нет.
final int getPendingCount()
Возвращает текущее значение счетчика ожидающих задач.
T getRawResult()
Возвращает результат вычисления.
final CountedCompleter<?> getRoot()
Возвращает корень текущего вычисления: эту задачу, если у нее нет завершающей задачи, иначе корень ее завершающей задачи.
final void helpComplete(int maxTasks)
Если эта задача не завершена, пытается обработать не более указанного количества других необработанных задач, для которых эта задача находится на пути завершения, если известно о наличии таких задач.
final CountedCompleter<?> nextComplete()
Если у этой задачи нет завершающей задачи, вызывает ForkJoinTask.quietlyComplete() и возвращает null.
void onCompletion(CountedCompleter<?> caller)
Выполняет действие при вызове метода tryComplete() с нулевым счетчиком ожидающих задач или при вызове безусловного метода complete(T).
boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller)
Выполняет действие при вызове метода ForkJoinTask.completeExceptionally(Throwable) или при возникновении исключения в методе compute(), если эта задача еще не была завершена обычным образом.
final void propagateCompletion()
Эквивалентен tryComplete(), но не вызывает onCompletion(CountedCompleter) на пути завершения: если счетчик ожидающих задач не равен нулю, уменьшает его; в противном случае аналогичным образом пытается завершить завершающую задачу этой задачи, если она существует, а если нет — помечает эту задачу как завершенную.
final void quietlyCompleteRoot()
Эквивалентен getRoot().quietlyComplete().
final void setPendingCount(int count)
Устанавливает счетчик ожидающих задач в указанное значение.
protected void setRawResult(T t)
Метод, который CountedCompleter с результатом может использовать для поддержки данных результата.
final void tryComplete()
Если счетчик ожидающих задач не равен нулю, уменьшает его; в противном случае вызывает onCompletion(CountedCompleter), а затем аналогичным образом пытается завершить завершающую задачу этой задачи, если она существует, а если нет — помечает эту задачу как завершенную.

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

adapt, adapt, adapt, adaptInterruptible, adaptInterruptible, adaptInterruptible, cancel, compareAndSetForkJoinTaskTag, 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
Модификатор и тип Метод Описание
static ForkJoinTask<?> adapt(Runnable runnable)
Возвращает новый ForkJoinTask, который выполняет метод run указанного Runnable в качестве действия и возвращает null при вызове ForkJoinTask.join().
static <T> ForkJoinTask<T> adapt(Runnable runnable, T result)
Возвращает новый ForkJoinTask, который выполняет метод run указанного Runnable в качестве действия и возвращает указанный результат при вызове ForkJoinTask.join().
static <T> ForkJoinTask<T> adapt(Callable<? extends T> callable)
Возвращает новый ForkJoinTask, который выполняет метод call указанного Callable в качестве действия и возвращает его результат при вызове ForkJoinTask.join(), преобразуя любые возникшие проверяемые исключения в RuntimeException.
static ForkJoinTask<?> adaptInterruptible(Runnable runnable)
Возвращает новый ForkJoinTask, который выполняет метод run указанного Runnable в качестве действия и возвращает null при вызове ForkJoinTask.join(), преобразуя любые возникшие проверяемые исключения в RuntimeException.
static <T> ForkJoinTask<T> adaptInterruptible(Runnable runnable, T result)
Возвращает новый ForkJoinTask, который выполняет метод run указанного Runnable в качестве действия и возвращает указанный результат при вызове ForkJoinTask.join(), преобразуя любые возникшие проверяемые исключения в RuntimeException.
static <T> ForkJoinTask<T> adaptInterruptible(Callable<? extends T> callable)
Возвращает новый ForkJoinTask, который выполняет метод call указанного Callable в качестве действия и возвращает его результат при вызове ForkJoinTask.join(), преобразуя любые возникшие проверяемые исключения в RuntimeException.
boolean cancel(boolean mayInterruptIfRunning)
Пытается отменить выполнение этой задачи.
final boolean compareAndSetForkJoinTaskTag(short expect, short update)
Атомарно устанавливает значение тега этой задачи при выполнении условия.
void completeExceptionally(Throwable ex)
Завершает эту задачу аварийно и, если она еще не прервана или не отменена, приводит к тому, что при join и связанных операциях она выбрасывает указанное исключение.
Throwable exceptionNow()
Возвращает исключение, выброшенное задачей, не дожидаясь ее завершения.
final ForkJoinTask<T> fork()
Организует асинхронное выполнение этой задачи в пуле, в котором выполняется текущая задача, если это применимо, или с использованием ForkJoinPool.commonPool(), если текущий поток ForkJoinTask.inForkJoinPool().
final T get()
При необходимости ожидает завершения вычисления, а затем извлекает его результат.
final T get(long timeout, TimeUnit unit)
При необходимости ожидает завершения вычисления не более указанного времени, а затем извлекает его результат, если он доступен.
final Throwable getException()
Возвращает исключение, выброшенное базовым вычислением, или CancellationException, если задача отменена, либо null, если исключения нет или метод еще не завершился.
final short getForkJoinTaskTag()
Возвращает тег этой задачи.
static ForkJoinPool getPool()
Возвращает пул, в котором выполняется текущий поток, или null, если текущий поток выполняется вне какого-либо ForkJoinPool.
static int getQueuedTaskCount()
Возвращает приблизительное количество задач, созданных текущим рабочим потоком, но еще не выполненных.
static int getSurplusQueuedTaskCount()
Возвращает приблизительную разницу между количеством задач в локальной очереди текущего рабочего потока и количеством других рабочих потоков, которые могут их перехватить, либо ноль, если этот поток не работает в ForkJoinPool.
static void helpQuiesce()
При необходимости выполняет задачи до тех пор, пока пул, в котором выполняется текущая задача, не перейдет в состояние покоя.
static boolean inForkJoinPool()
Возвращает true, если текущий поток является ForkJoinWorkerThread, выполняющим вычисление ForkJoinPool.
final T invoke()
Начинает выполнение этой задачи, при необходимости ожидает ее завершения и возвращает результат либо выбрасывает (непроверяемое) исключение RuntimeException или Error, если такое исключение возникло при базовом вычислении.
static <T extends ForkJoinTask<?>>
Collection<T>
invokeAll(Collection<T> tasks)
Разветвляет все задачи в указанной коллекции и возвращает управление, когда для каждой задачи выполняется условие isDone или возникает (непроверяемое) исключение, которое в этом случае повторно выбрасывается.
static void invokeAll(ForkJoinTask<?>... tasks)
Разветвляет указанные задачи и возвращает управление, когда для каждой задачи выполняется условие isDone или возникает (непроверяемое) исключение, которое в этом случае повторно выбрасывается.
static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2)
Разветвляет указанные задачи и возвращает управление, когда для каждой задачи выполняется условие isDone или возникает (непроверяемое) исключение, которое в этом случае повторно выбрасывается.
final boolean isCancelled()
Возвращает true, если эта задача была отменена до ее обычного завершения.
final boolean isCompletedAbnormally()
Возвращает true, если эта задача выбросила исключение или была отменена.
final boolean isCompletedNormally()
Возвращает true, если эта задача завершилась без выбрасывания исключения и не была отменена.
final boolean isDone()
Возвращает true, если эта задача завершилась.
final T join()
Возвращает результат вычисления, когда оно завершено.
protected static ForkJoinTask<?> peekNextLocalTask()
Возвращает, но не удаляет из очереди и не выполняет задачу, поставленную в очередь текущим потоком, но еще не выполненную, если такая задача доступна немедленно.
protected static ForkJoinTask<?> pollNextLocalTask()
Удаляет из очереди и возвращает, не выполняя, следующую задачу, поставленную в очередь текущим потоком, но еще не выполненную, если текущий поток работает в ForkJoinPool.
protected static ForkJoinTask<?> pollSubmission()
Если текущий поток работает в ForkJoinPool, удаляет из очереди и возвращает, не выполняя, задачу, отправленную в пул извне, если такая задача доступна.
protected static ForkJoinTask<?> pollTask()
Если текущий поток работает в ForkJoinPool, удаляет из очереди и возвращает, не выполняя, следующую задачу, поставленную в очередь текущим потоком, но еще не выполненную, если она доступна; в противном случае возвращает задачу, созданную другим потоком, если такая задача доступна.
final void quietlyComplete()
Обычно завершает эту задачу, не устанавливая значение.
final void quietlyInvoke()
Начинает выполнение этой задачи и при необходимости ожидает ее завершения, не возвращая результат и не выбрасывая исключение.
final void quietlyJoin()
Ожидает завершения этой задачи, не возвращая результат и не выбрасывая исключение.
final boolean quietlyJoin(long timeout, TimeUnit unit)
Пытается дождаться завершения этой задачи; возвращает true, если задача завершилась (возможно, аварийно) до истечения указанного времени ожидания и текущий поток не был прерван.
final boolean quietlyJoinUninterruptibly(long timeout, TimeUnit unit)
Пытается дождаться завершения этой задачи; возвращает true, если задача завершилась (возможно, аварийно) до истечения указанного времени ожидания.
void reinitialize()
Сбрасывает внутреннее состояние учета этой задачи, позволяя впоследствии выполнить fork.
T resultNow()
Возвращает вычисленный результат, не дожидаясь завершения.
final short setForkJoinTaskTag(short newValue)
Атомарно устанавливает значение тега этой задачи и возвращает его старое значение.
Future.State state()
Возвращает состояние вычисления.
boolean tryUnfork()
Пытается удалить эту задачу из очереди выполнения.

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

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Модификатор и тип Метод Описание
protected Object clone()
Создает и возвращает копию этого объекта.
boolean equals(Object obj)
Указывает, равен ли какой-либо другой объект этому объекту.
protected void finalize()
Устарело, будет удалено: этот элемент API может быть удален в будущей версии.
Финализация устарела и может быть удалена в одном из будущих выпусков.
final Class<?> getClass()
Возвращает класс времени выполнения этого Object.
int hashCode()
Возвращает хеш-код этого объекта.
final void notify()
Пробуждает один поток, ожидающий на мониторе этого объекта.
final void notifyAll()
Пробуждает все потоки, ожидающие на мониторе этого объекта.
String toString()
Возвращает строковое представление объекта.
final void wait()
Заставляет текущий поток ожидать пробуждения, обычно вследствие уведомления или прерывания.
final void wait(long timeoutMillis)
Заставляет текущий поток ожидать пробуждения, обычно вследствие уведомления или прерывания, либо истечения указанного периода реального времени.
final void wait(long timeoutMillis, int nanos)
Заставляет текущий поток ожидать пробуждения, обычно вследствие уведомления или прерывания, либо истечения указанного периода реального времени.

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

CountedCompleter

protected CountedCompleter(CountedCompleter<?> completer, int initialPendingCount)
Создает новый CountedCompleter с указанной задачей-завершителем и начальным значением счетчика ожидающих.
Параметры:
completer — задача-завершитель этой задачи или null, если ее нет
initialPendingCount — начальное значение счетчика ожидающих

CountedCompleter

protected CountedCompleter(CountedCompleter<?> completer)
Создает новый CountedCompleter с указанной задачей-завершителем и начальным значением счетчика ожидающих, равным нулю.
Параметры:
completer — задача-завершитель этой задачи или null, если ее нет

CountedCompleter

protected CountedCompleter()
Создает новый CountedCompleter без задачи-завершителя и с начальным значением счетчика ожидающих, равным нулю.

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

compute

public abstract void compute()
Основное вычисление, выполняемое этой задачей.

onCompletion

public void onCompletion(CountedCompleter<?> caller)
Выполняет действие при вызове метода tryComplete(), когда счетчик ожидающих равен нулю, или при вызове безусловного метода complete(T). По умолчанию этот метод ничего не делает. Различить случаи можно, проверив идентичность заданного аргумента caller. Если он не равен this, то обычно это подзадача, которая может содержать результаты (и/или ссылки на другие результаты) для объединения.
Параметры:
caller — задача, вызывающая этот метод (ей может быть сама эта задача)

onExceptionalCompletion

public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller)
Выполняет действие при вызове метода ForkJoinTask.completeExceptionally(Throwable) или при выбрасывании исключения методом compute(), если эта задача еще не завершилась нормально иным способом. При входе в этот метод эта задача ForkJoinTask.isCompletedAbnormally(). Возвращаемое значение метода определяет дальнейшее распространение исключения: если true и у этой задачи есть задача-завершитель, которая еще не завершена, то эта задача-завершитель также завершается с исключением, совпадающим с исключением этой задачи. Реализация этого метода по умолчанию ничего не делает и возвращает true.
Параметры:
ex — исключение
caller — задача, вызывающая этот метод (ей может быть сама эта задача)
Возвращает:
true, если это исключение следует распространить на задачу-завершитель этой задачи, если она есть

getCompleter

public final CountedCompleter<?> getCompleter()
Возвращает задачу-завершитель, заданную в конструкторе этой задачи, или null, если ее нет.
Возвращает:
задачу-завершитель

getPendingCount

public final int getPendingCount()
Возвращает текущее значение счетчика ожидающих.
Возвращает:
текущее значение счетчика ожидающих

setPendingCount

public final void setPendingCount(int count)
Устанавливает счетчик ожидающих в заданное значение.
Параметры:
count — значение счетчика

addToPendingCount

public final void addToPendingCount(int delta)
Атомарно добавляет заданное значение к счетчику ожидающих.
Параметры:
delta — добавляемое значение

compareAndSetPendingCount

public final boolean compareAndSetPendingCount(int expected, int count)
Атомарно устанавливает для счетчика ожидающих заданное значение, только если его текущее значение совпадает с заданным ожидаемым значением.
Параметры:
expected — ожидаемое значение
count — новое значение
Возвращает:
true, если операция выполнена успешно

decrementPendingCountUnlessZero

public final int decrementPendingCountUnlessZero()
Атомарно уменьшает счетчик ожидающих на единицу, если он не равен нулю.
Возвращает:
начальное значение счетчика ожидающих (до уменьшения), имевшееся при входе в этот метод

getRoot

public final CountedCompleter<?> getRoot()
Возвращает корневую задачу текущего вычисления: саму эту задачу, если у нее нет задачи-завершителя, иначе корневую задачу ее задачи-завершителя.
Возвращает:
корневую задачу текущего вычисления

tryComplete

public final void tryComplete()
Если счетчик ожидающих не равен нулю, уменьшает его на единицу; в противном случае вызывает onCompletion(CountedCompleter), а затем аналогичным образом пытается завершить задачу-завершитель этой задачи, если она есть, иначе помечает эту задачу как завершенную.

propagateCompletion

public final void propagateCompletion()
Эквивалентен tryComplete(), но не вызывает onCompletion(CountedCompleter) в цепочке завершения: если счетчик ожидающих не равен нулю, уменьшает его на единицу; в противном случае аналогичным образом пытается завершить задачу-завершитель этой задачи, если она есть, иначе помечает эту задачу как завершенную. Этот метод может быть полезен в случаях, когда onCompletion не следует или не требуется вызывать для каждой задачи-завершителя в вычислении.

complete

public void complete(T rawResult)
Независимо от значения счетчика ожидающих вызывает onCompletion(CountedCompleter), помечает эту задачу как завершенную и дополнительно вызывает tryComplete() для задачи-завершителя этой задачи, если она есть. Заданный rawResult используется как аргумент метода setRawResult(T) перед вызовом onCompletion(CountedCompleter) или пометкой этой задачи как завершенной; его значение имеет смысл только для классов, переопределяющих setRawResult. Этот метод не изменяет счетчик ожидающих.

Этот метод может быть полезен, когда требуется принудительно завершить задачу сразу после получения любого одного результата подзадачи (а не всех результатов). Однако в распространенном (и рекомендуемом) случае, когда setRawResult не переопределен, такого эффекта проще добиться с помощью quietlyCompleteRoot().

Переопределяет:
complete в классе ForkJoinTask<T>
Параметры:
rawResult — необработанный результат

firstComplete

public final CountedCompleter<?> firstComplete()
Если счетчик ожидающих этой задачи равен нулю, возвращает эту задачу; в противном случае уменьшает ее счетчик ожидающих на единицу и возвращает null. Этот метод предназначен для использования вместе с nextComplete() в циклах обхода завершения.
Возвращает:
эту задачу, если счетчик ожидающих был равен нулю, иначе null

nextComplete

public final CountedCompleter<?> nextComplete()
Если у этой задачи нет задачи-завершителя, вызывает ForkJoinTask.quietlyComplete() и возвращает null. Если счетчик ожидающих задачи-завершителя не равен нулю, уменьшает этот счетчик на единицу и возвращает null. В противном случае возвращает задачу-завершитель. Этот метод можно использовать в цикле обхода завершения для однородных иерархий задач:
for (CountedCompleter<?> c = firstComplete();
     c != null;
     c = c.nextComplete()) {
  // ... process c ...
}
Возвращает:
задачу-завершитель или null, если ее нет

quietlyCompleteRoot

public final void quietlyCompleteRoot()
Эквивалентен getRoot().quietlyComplete().

helpComplete

public final void helpComplete(int maxTasks)
Если эта задача еще не завершена, пытается обработать не более заданного числа других необработанных задач, для которых эта задача входит в цепочку завершения, если известно о наличии таких задач.
Параметры:
maxTasks — максимальное число задач для обработки. Если значение меньше или равно нулю, задачи не обрабатываются.

exec

protected final boolean exec()
Реализует соглашения о выполнении для CountedCompleter.
Определен в:
exec в классе ForkJoinTask<T>
Возвращает:
true, если известно, что эта задача завершилась нормально

getRawResult

public T getRawResult()
Возвращает результат вычисления. По умолчанию возвращает null, что подходит для действий Void, но в остальных случаях этот метод следует переопределить — почти всегда так, чтобы он возвращал поле или значение функции от поля, в котором хранится результат после завершения.
Определен в:
getRawResult в классе ForkJoinTask<T>
Возвращает:
результат вычисления

setRawResult

protected void setRawResult(T t)
Метод, который CountedCompleter с результатом может использовать для поддержки данных результата. По умолчанию ничего не делает. Переопределять его не рекомендуется. Однако если этот метод переопределен для обновления существующих объектов или полей, его реализация, как правило, должна быть потокобезопасной.
Определен в:
setRawResult в классе ForkJoinTask<T>
Параметры:
t — значение

Сообщить об ошибке или предложить улучшение
Дополнительную справочную информацию по API и документацию для разработчиков см. в разделе Документация Java SE, содержащем более подробные описания для разработчиков, обзоры основных понятий, определения терминов, обходные решения и примеры работающего кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или ее аффилированных лиц в США и других странах.
Авторские права © 1993, 2026, 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.

Spec-Zone.ru

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