ForkJoinPool简述
ForkJoinPool不是ExecutorService的替代,而是对其的补充 Java Tip: When to use ForkJoinPool vs ExecutorService;ForkJoinPool 最适合的是计算密集型的任务,如果存在I/O,线程间同步,sleep() 等会造成线程长时间阻塞的情况时,最好配合使用ManagedBlocker;Work-Stealing 的适用场景是不同的任务的耗时相差比较大,即某些任务需要运行较长时间,而某些任务会很快的运行完成,这种情况下用 Work-Stealing 很合适;但是如果任务的耗时很平均,则此时 Work-Stealing 并不适合,因为窃取任务时不同线程需要抢占锁;ForkJoinPool是分而治之的思想的体现。
使用
- 对于要返回结果的情况,直接继承 RecursiveTask
- 对于无需返回结果的情况,直接继承 RecursiveAction
invoke是阻塞的,带有返回值的:
使用ForkJoinPool计算求和示例
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
public class SumTask extends RecursiveTask<Integer> {
private int THREHOLD = 10;
private int[] src;
private Integer left;
private Integer right;
public SumTask(int[] src, Integer left, Integer right) {
this.src = src;
this.left = left;
this.right = right;
}
@Override
protected Integer compute() {
if ((right - left) < THREHOLD) {
Integer sum = 0;
System.out.println(left + " to " + right);
for (int i = left; i <= right; i++)
sum += src[i];
return sum;
}
//拆分数组
Integer mid = (left + right) >> 1;
SumTask leftTask = new SumTask(src, left, mid);
SumTask rightTask = new SumTask(src, mid + 1, right);
invokeAll(leftTask, rightTask);
return leftTask.join() + rightTask.join();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//生成随机数组
int[] a = ArrayUtils.makeArray(45);
// System.out.println("单线程执行结果: " + ArrayUtils.sum(a));
ForkJoinPool forkJoinPool = new ForkJoinPool();
SumTask task = new SumTask(a, 0, a.length - 1);
//提交任务
ForkJoinTask<Integer> result = forkJoinPool.submit(task);
System.out.println("fork.join执行结果: " + result.get());
}
}
执行结果如下