Класс CountedCompleter<T>
- Параметры типа:
-
T- тип результата завершения
- Все реализуемые интерфейсы:
-
Serializable,Future<T>
public abstract class CountedCompleter<T> extends ForkJoinTask<T>
ForkJoinTask with a completion action performed when triggered and there are no remaining pending actions. CountedCompleters are in general more robust in the presence of subtask stalls and blockage than are other forms of ForkJoinTasks, but are less intuitive to program. Uses of CountedCompleter are similar to those of other completion based components (such as CompletionHandler) except that multiple pending completions may be necessary to trigger the completion action onCompletion(CountedCompleter), not just one. Unless initialized otherwise, the pending count starts at zero, but may be (atomically) changed using methods setPendingCount(int), addToPendingCount(int), and compareAndSetPendingCount(int, int). Upon invocation of tryComplete(), if the pending action count is nonzero, it is decremented; otherwise, the completion action is performed, and if this completer itself has a completer, the process is continued with its completer. As is the case with related synchronization components such as Phaser and Semaphore, these methods affect only internal counts; they do not establish any further internal bookkeeping. In particular, the identities of pending tasks are not maintained. As illustrated below, you can create subclasses that do record some or all pending tasks or their results when needed. As illustrated below, utility methods supporting customization of completion traversals are also provided. However, because CountedCompleters provide only basic synchronization mechanisms, it may be useful to create further abstract subclasses that maintain linkages, fields, and additional support methods appropriate for a set of related usages. A concrete CountedCompleter class must define method compute(), that should in most cases (as illustrated below), invoke tryComplete() once before returning. The class may also optionally override method onCompletion(CountedCompleter) to perform an action upon normal completion, and method onExceptionalCompletion(Throwable, CountedCompleter) to perform an action upon any exception.
CountedCompleters most often do not bear results, in which case they are normally declared as CountedCompleter<Void>, and will always return null as a result value. In other cases, you should override method getRawResult() to provide a result from join(), invoke(), and related methods. In general, this method should return the value of a field (or a function of one or more fields) of the CountedCompleter object that holds the result upon completion. Method setRawResult(T) by default plays no role in CountedCompleters. It is possible, but rarely applicable, to override this method to maintain other objects or fields holding result data.
A CountedCompleter that does not itself have a completer (i.e., one for which getCompleter() returns null) can be used as a regular ForkJoinTask with this added functionality. However, any completer that in turn has another completer serves only as an internal helper for other computations, so its own task status (as reported in methods such as ForkJoinTask.isDone()) is arbitrary; this status changes only upon explicit invocations of complete(T), ForkJoinTask.cancel(boolean), ForkJoinTask.completeExceptionally(Throwable) or upon exceptional completion of method compute. Upon any exceptional completion, the exception may be relayed to a task's completer (and its completer, and so on), if one exists and it has not otherwise already completed. Similarly, cancelling an internal CountedCompleter has only a local effect on that completer, so is not often useful.
Примеры использования.
Параллельное рекурсивное разбиение. CountedCompleters могут быть организованы в деревья, аналогичные тем, которые часто используются с RecursiveActions, хотя конструкции, связанные с их настройкой, обычно отличаются. Здесь completer каждого задания является его родителем в дереве вычислений. Несмотря на то, что они требуют немного большего учёта, CountedCompleters могут быть лучшим выбором при применении потенциально длительной операции (которая не может быть далее разделена) к каждому элементу массива или коллекции; особенно когда операция занимает значительно разное время для завершения для некоторых элементов, либо из-за внутренней вариативности (например, ввода-вывода), либо из-за побочных эффектов, таких как сборка мусора. Поскольку CountedCompleters предоставляют свои собственные продолжения, другим задачам не нужно блокироваться в ожидании их выполнения.
Например, вот начальная версия утилитарного метода, использующего рекурсивное разбиение пополам, чтобы разбить работу на отдельные части (задания листьев). Даже когда работа разбивается на отдельные вызовы, древовидные методы обычно предпочтительнее непосредственного создания дочерних заданий, так как они уменьшают межпоточную коммуникацию и улучшают балансировку нагрузки. В рекурсивном случае второе из каждой пары дочерних задач, завершающих выполнение, инициирует завершение их родителя (поскольку не выполняется никакая комбинация результатов, по умолчанию не реализуется метод 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();
} Дополнительная оптимизация таких классов может включать специализацию классов для шагов листьев, деление не пополам, а, скажем, по четверо на каждой итерации и использование адаптивного порога вместо постоянного деления до одного элемента. Поиск. Дерево CountedCompleters может искать значение или свойство в различных частях структуры данных и сообщать результат в 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();
}
} Триггеры. Некоторые CountedCompleters сами никогда не разветвляются, а вместо этого служат элементами магистрали в других конструкциях; включая те, в которых завершение одной или нескольких асинхронных задач запускает другую асинхронную задачу. Например:
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();
- Since:
- 1.8
- См. также:
Краткое описание вложенных классов
Вложенные классы/интерфейсы, объявленные в интерфейсе java.util.concurrent.Future
Future.State
Краткое описание конструкторов
| Модификатор | Конструктор | Описание |
|---|---|---|
protected |
Создаёт новый CountedCompleter без компаратора и начальным значением pending count равным нулю. |
|
protected |
Создаёт новый CountedCompleter с заданным компаратором и начальным значением pending count равным нулю. |
|
protected |
Создаёт новый CountedCompleter с заданным компаратором и начальным значением pending count. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
final void |
addToPendingCount |
Добавляет (атомарно) заданное значение к pending count. |
final boolean |
compareAndSetPendingCount |
Устанавливает (атомарно) pending count в заданное значение, только если текущее значение совпадает с ожидаемым. |
void |
complete |
Независимо от pending count, вызывает onCompletion(CountedCompleter), отмечает задачу как завершенную и дополнительно запускает tryComplete() на компараторе этой задачи, если он существует. |
abstract void |
compute() |
Основной вычисление, выполняемое этой задачей. |
final int |
decrementPendingCountUnlessZero() |
Если pending count не равен нулю, (атомарно) уменьшает его. |
protected final boolean |
exec() |
Реализует соглашения об выполнении для CountedCompleters. |
final CountedCompleter |
firstComplete() |
Если pending count этой задачи равен нулю, возвращает эту задачу; в противном случае уменьшает pending count и возвращает null. |
final CountedCompleter |
getCompleter() |
Возвращает компаратор, установленный в конструкторе этой задачи, или null если его нет. |
final int |
getPendingCount() |
Возвращает текущее значение pending count. |
T |
getRawResult() |
Возвращает результат вычисления. |
final CountedCompleter |
getRoot() |
Возвращает корень текущего вычисления; т.е., эту задачу, если у неё нет компаратора, иначе компаратор корня. |
final void |
helpComplete |
Если эта задача ещё не завершена, пытается обработать не более заданного числа других необработанных задач, для которых эта задача находится на пути завершения, если они известны. |
final CountedCompleter |
nextComplete() |
Если у этой задачи нет компаратора, вызывает ForkJoinTask.quietlyComplete() и возвращает null. |
void |
onCompletion |
Выполняет действие при вызове метода tryComplete() и pending count равен нулю, или при вызове безусловного метода complete(T). |
boolean |
onExceptionalCompletion |
Выполняет действие при вызове метода ForkJoinTask.completeExceptionally(Throwable) или при выбрасывании исключения методом compute(), и эта задача ещё не завершена другим способом. |
final void |
propagateCompletion() |
Эквивалентно tryComplete(), но не вызывает onCompletion(CountedCompleter) вдоль пути завершения: Если pending count не равен нулю, уменьшает счётчик; в противном случае аналогично пытается завершить компаратор этой задачи, если он существует, иначе отмечает задачу как завершенную. |
final void |
quietlyCompleteRoot() |
Эквивалентно getRoot().quietlyComplete(). |
final void |
setPendingCount |
Устанавливает pending count в заданное значение. |
protected void |
setRawResult |
Метод, который result-bearing CountedCompleters могут использовать по желанию, чтобы помочь сохранить данные результатов. |
final void |
tryComplete() |
Если pending count не равен нулю, уменьшает счётчик; в противном случае вызывает onCompletion(CountedCompleter) и затем аналогично пытается завершить компаратор этой задачи, если он существует, иначе отмечает задачу как завершенную. |
Методы, объявленные в классе java.util.concurrent.ForkJoinTask
adapt, adapt, adapt, adaptInterruptible, cancel, compareAndSetForkJoinTaskTag, completeExceptionally, 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, setForkJoinTaskTag, tryUnfork
Методы, объявленные в классе java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Методы, объявленные в интерфейсе java.util.concurrent.Future
exceptionNow, resultNow, state
Подробное описание конструкторов
CountedCompleter
protected CountedCompleter(CountedCompleter<?> completer, int initialPendingCount)
- Параметры:
-
completer- completer данной задачи, илиnullв случае отсутствия -
initialPendingCount- начальное количество ожидающих задач
CountedCompleter
protected CountedCompleter(CountedCompleter<?> completer)
- Параметры:
-
completer- completer данной задачи, илиnullв случае отсутствия
CountedCompleter
protected CountedCompleter()
Подробное описание методов
compute
public abstract void compute()
onCompletion
public void onCompletion(CountedCompleter<?> caller)
tryComplete() и количестве ожидающих задач равном нулю, или при вызове безусловного метода complete(T). По умолчанию этот метод ничего не делает. Вы можете различать случаи, проверяя идентичность переданного аргумента вызывающего объекта. Если он не равен
this, это обычно означает, что это подзадача, которая может содержать результаты (и/или ссылки на другие результаты) для объединения.- Параметры:
-
caller- задача, вызывающая этот метод (которая может быть этой задачей)
onExceptionalCompletion
public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller)
ForkJoinTask.completeExceptionally(Throwable) или при возникновении исключения в методе compute(), и эта задача ещё не завершилась нормальным образом. В момент входа в этот метод, задача ForkJoinTask.isCompletedAbnormally(). Значение возвращаемого значения этого метода определяет дальнейшее распространение: если true, и у этой задачи есть completer, который ещё не завершён, то этот completer также завершается с исключением, таким же, как у этого completer. По умолчанию этот метод ничего не делает, кроме возвращения true. - Параметры:
-
ex- исключение -
caller- задача, вызывающая этот метод (которая может быть этой задачей) - Возвращает:
-
trueесли это исключение должно быть передано completer этой задачи, если он существует
getCompleter
public final CountedCompleter<?> getCompleter()
null в случае отсутствия.- Возвращает:
- completer
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) и затем аналогично пытается завершить completer этой задачи, если он существует, в противном случае помечает эту задачу как завершённую.propagateCompletion
public final void propagateCompletion()
tryComplete(), но не вызывает onCompletion(CountedCompleter) вдоль пути завершения: Если количество ожидающих задач не равно нулю, уменьшает счётчик; в противном случае аналогично пытается завершить completer этой задачи, если он существует, в противном случае помечает эту задачу как завершённую. Этот метод может быть полезен в случаях, когда onCompletion не должен или не должен вызываться для каждого completer в вычислении.complete
public void complete(T rawResult)
onCompletion(CountedCompleter), помечает эту задачу как завершённую и запускает tryComplete() на completer этой задачи, если он существует. Переданное значение rawResult используется в качестве аргумента setRawResult(T) до вызова onCompletion(CountedCompleter) или помечания этой задачи как завершённой; его значение имеет смысл только для классов, переопределяющих setRawResult. Этот метод не изменяет счётчик ожидающих задач. Этот метод может быть полезен, когда необходимо форсировать завершение, как только будет получен результат одной (а не всех) подзадач. Однако в общем случае (и рекомендуемом), когда
setRawResult не переопределён, этот эффект можно получить проще с помощью quietlyCompleteRoot().
- Overrides:
-
completeв классеForkJoinTask<T> - Параметры:
-
rawResult- сырой результат
firstComplete
public final CountedCompleter<?> firstComplete()
null. Этот метод предназначен для использования с nextComplete() в циклах обработки завершения.- Возвращает:
- эту задачу, если количество ожидающих задач было равно нулю, иначе
null
nextComplete
public final CountedCompleter<?> nextComplete()
ForkJoinTask.quietlyComplete() и возвращает null. Или, если количество ожидающих задач completer не равно нулю, уменьшает это количество и возвращает null. В противном случае возвращает completer. Этот метод может использоваться в качестве части цикла обработки завершения для однородных иерархий задач:
for (CountedCompleter<?> c = firstComplete();
c != null;
c = c.nextComplete()) {
// ... process c ...
}
- Возвращает:
- completer, или
nullесли его нет
quietlyCompleteRoot
public final void quietlyCompleteRoot()
getRoot().quietlyComplete().helpComplete
public final void helpComplete(int maxTasks)
- Параметры:
-
maxTasks- максимальное количество задач для обработки. Если меньше или равно нулю, то задачи не обрабатываются.
exec
protected final boolean exec()
- Определено в:
-
execв классеForkJoinTask<T> - Возвращает:
-
trueесли эта задача завершилась нормально
getRawResult
public T getRawResult()
null, что подходит для Void действий, но в других случаях следует переопределить, почти всегда для возвращения поля или функции поля, которое хранит результат после завершения.- Определено в:
-
getRawResultв классеForkJoinTask<T> - Возвращает:
- результат вычисления
setRawResult
protected void setRawResult(T t)
- Определено в:
-
setRawResultв классеForkJoinTask<T> - Параметры:
-
t- значение
© 1993, 2023, 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/21/docs/api/java.base/java/util/concurrent/CountedCompleter.html