什么是分支合并框架呢
原理:
Fork:把一个复杂任务进行分拆,大事化小(黑色箭头)
Join:把分拆任务的结果进行合并(蓝色箭头)
相关的类:
1:ForkJoinPool
拆分成多个的小任务就在这个池子运行
分支合并池 类比=> 线程池
2:ForkJoinTask:
ForkJoinTask 类比=> FutureTask
同样是实现了Future接口;
所以在使用ForkJoinTask.get()一样,得执行完得出结果才会的得到值
3:RecursiveTask
递归任务:继承后可以实现递归(自己调自己)调用的任务
需要注意:需要设置结束拆分的条件避免内存溢出
通过分支合并框架来计算0-100相加之和:
/**
* 这个类主要演示的是java分支合并框架的例子:
* ForkJoinPool
* ForkJoinTask
* RecursiveTask
*
*
* @Author:LRC
* @Date:11:15 上午 2020/7/7
*/
public class ForkJoinDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//制定任务
MyTask myTask = new MyTask(0, 100);
//创造池
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Integer> forkJoinTask = forkJoinPool.submit(myTask);
System.out.println(forkJoinTask.get());
}
}
/**
* MyTask的任务是计算从0加到100
*
*
* @Author:LRC
* @Date:11:16 上午 2020/7/7
*/
class MyTask extends RecursiveTask<Integer>{
public static final int ADJAST_VALUES=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() {
//判断end-begin>=ADJAST_VALUES 就不进行拆分
//同时这个判断条件使这个递归不会无限,
if ((end-begin)<=ADJAST_VALUES){
for (int i = begin; i <= end; i++) {
result=result+i;
}
}else {
//通过做中间值拆成两份
int mid=(begin+end)/2;
//递归拆分
MyTask myTask1 = new MyTask(begin, mid);
MyTask myTask2 = new MyTask(mid+1, end);
myTask1.fork();
myTask2.fork();
result= myTask1.join()+myTask2.join();
}
return result;
}
}
先制定任务实现递归任务接口,实现递归拆解,很重要的一步就是找到递归结束的条件,这样才可以避免溢出异常;
了解下RecuriRecursiveTask接口的fork 源码:
可以看到将拆分this加入线程队列push进去,
结果通过join方法返回;
使用:
在主线程中:需要
- 1:需要制定任务-mytask
- 2:创造池
- 3:提交任务返回ForkJoinTask
- 4:ForkJoinTask实现的是Future接口,只有计算完后,通过get()方法获取返回结果