Java 中的 ForkJoin 任務
Java 中的 fork / join 框架非常適合於可以分成更小部分並且並行求解的問題。fork / join 問題的基本步驟是:
- 將問題分成多個部分
- 將每個部件彼此平行地求解
- 將每個子解決方案組合成一個整體解決方案
一個 ForkJoinTask 是定義這樣的問題的介面。通常期望你將其一個抽象實現(通常是 RecursiveTask ) 子類化,而不是直接實現介面。
在這個例子中,我們將總結一個整數的集合,直到我們得到不超過 10 的批量大小。
import java.util.List;
import java.util.concurrent.RecursiveTask;
public class SummingTask extends RecursiveTask<Integer> {
private static final int MAX_BATCH_SIZE = 10;
private final List<Integer> numbers;
private final int minInclusive, maxExclusive;
public SummingTask(List<Integer> numbers) {
this(numbers, 0, numbers.size());
}
// This constructor is only used internally as part of the dividing process
private SummingTask(List<Integer> numbers, int minInclusive, int maxExclusive) {
this.numbers = numbers;
this.minInclusive = minInclusive;
this.maxExclusive = maxExclusive;
}
@Override
public Integer compute() {
if (maxExclusive - minInclusive > MAX_BATCH_SIZE) {
// This is too big for a single batch, so we shall divide into two tasks
int mid = (minInclusive + maxExclusive) / 2;
SummingTask leftTask = new SummingTask(numbers, minInclusive, mid);
SummingTask rightTask = new SummingTask(numbers, mid, maxExclusive);
// Submit the left hand task as a new task to the same ForkJoinPool
leftTask.fork();
// Run the right hand task on the same thread and get the result
int rightResult = rightTask.compute();
// Wait for the left hand task to complete and get its result
int leftResult = leftTask.join();
// And combine the result
return leftResult + rightResult;
} else {
// This is fine for a single batch, so we will run it here and now
int sum = 0;
for (int i = minInclusive; i < maxExclusive; i++) {
sum += numbers.get(i);
}
return sum;
}
}
}
現在可以將此任務的例項傳遞給 ForkJoinPool 的例項。
// Because I am not specifying the number of threads
// it will create a thread for each available processor
ForkJoinPool pool = new ForkJoinPool();
// Submit the task to the pool, and get what is effectively the Future
ForkJoinTask<Integer> task = pool.submit(new SummingTask(numbers));
// Wait for the result
int result = task.join();