12 Fork 与 Join分支
将一个大的任务拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果。
该算法相当于递归,且是二分查找思路
class Fibonacci extends RecursiveTask<Integer> {
final int n;
Fibonacci(int n) { this.n = n; }
Integer compute() {
if (n <= 1)
return n;
Fibonacci f1 = new Fibonacci(n - 1);
// 分支
f1.fork();
Fibonacci f2 = new Fibonacci(n - 2);
// 合并
return f2.compute() + f1.join();
}
}
Fork:把一个复杂任务进行分拆,大事化小
Join:把分拆任务的结果进行合并
ForkJoinTask:我们要使用 Fork/Join 框架,首先需要创建一个 ForkJoin 任务。该类提供了在任务中执行 fork 和 join 的机制。通常情况下我们不需要直接集成 ForkJoinTask 类,只需要继承它的子类,Fork/Join 框架提供了两个子类:
RecursiveAction:用于没有返回结果的任务
RecursiveTask:用于有返回结果的任务
ForkJoinPool:ForkJoinTask 需要通过 ForkJoinPool 来执行
RecursiveTask:继承后可以实现递归(自己调自己)调用的任务
创建分支合并对象 通过该对象调用内部方法
具体案例:1加到100,相加两个数值不能大于10
class MyTask extends RecursiveTask<Integer> {
// 拆分差值不能超过10
private static final Integer VALUE = 10;
private int begin;
private int end;
private int result;
public MyTask(int begin, int end){
this.begin = begin;
this.end = end;
}
@Override
protected Integer compute() {
// 判断两个值的差值是否大于10
if((end-begin)<=10) {
// 相加操作
for (int i = begin; i <= end ; i++) {
result = result + i;
}
} else {
// 大于10 继续拆分
int middle = (begin + end) / 2;
// 拆分左边
MyTask task01 = new MyTask(begin, middle);
// 拆分右边
MyTask task02 = new MyTask(middle + 1, end);
// 调用方法拆分
task01.fork();
task02.fork();
// 合并结果
result = task01.join() + task02.join();
}
return result;
}
}
public class ForkJoinTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建MyTask对象
MyTask task = new MyTask(0, 100);
// 创建分支合并池对象
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Integer> forkJoinTask = forkJoinPool.submit(task);
// 获取最终合并之后结果
Integer reslut = forkJoinTask.get();
System.out.println(reslut);
}
}
输出结果:
5050