Класс 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. Поскольку 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));
}
}
}
Следующий пример иллюстрирует некоторые усовершенствования и идиомы, которые могут привести к лучшей производительности: RecursiveActions необязательно должны быть полностью рекурсивными, если они сохраняют базовый подход «разделяй и властвуй». Вот класс, который суммирует квадраты каждого элемента массива 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
- См. также:
- Сериализованная форма
Конструкторы
| Конструктор и описание |
|---|
RecursiveAction()
|
Методы
| Модификатор и тип | Метод и описание |
|---|---|
protected abstract void |
compute() Основное вычисление, выполняемое этой задачей. |
protected boolean |
exec() Реализует соглашения об выполнении для RecursiveActions. |
Void |
getRawResult() Всегда возвращает |
protected void |
setRawResult(Void mustBeNull) Требует значение завершения null. |
Методы, унаследованные от класса java.util.concurrent.ForkJoinTask
adapt, adapt, adapt, cancel, compareAndSetForkJoinTaskTag, complete, completeExceptionally, fork, get, get, getException, getForkJoinTaskTag, getPool, getQueuedTaskCount, getSurplusQueuedTaskCount, helpQuiesce, inForkJoinPool, invoke, invokeAll, invokeAll, invokeAll, isCancelled, isCompletedAbnormally, isCompletedNormally, isDone, join, peekNextLocalTask, pollNextLocalTask, pollTask, quietlyComplete, quietlyInvoke, quietlyJoin, reinitialize, setForkJoinTaskTag, tryUnfork
Методы, унаследованные от класса java.lang.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()
Реализует соглашения об выполнении для RecursiveActions.
- Задано:
-
execв классеForkJoinTask<Void> - Возвращает:
-
trueесли известно, что эта задача завершилась нормально
© 1993, 2020, 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.