for-join框架主要是用来支持执行计算密集型任务的,比如图像、视频处理等
其工作原理是:
我们将大的复杂的计算任务划分为无数的小任务(我看了下源码,所有的小任务都被放在了一个队列里面),最后将各个小任务的处理结果整合返回(递归思想)
,如果有多余的处理器的话,这些小任务可以并行运算。
下面我们来看一个例子:在一个大的int数组(存放的值为 0-100的随机数),我们将计算数组中数值大于
50的元素个数。
1 首先新建一个继承 RecursiveTask<Integer>抽象类的Counter类,这个类的思想是
如果本次任务处理的数字大于某个指定的值(下面类中的size),则继续将这个任务划分为子任务,直到子任务处理的数组大小 小于指定值再处理
public class Counter extends RecursiveTask<Integer>{
private int[] values;//被计算的数组
private int from;//起始值
private int to;//结束值
private Predicate<Integer> p;//定义的 大于50的赛选规则
private int size;//单词计算(x小任务处理的数组大小)
public Counter(int[] values,int from,int to,Predicate<Integer> p,int size){
this.values = values;
this.from = from;
this.to = to;
this.p = p;
this.size = size;
}
@Override
protected Integer compute() {
int count = 0;
if(to - from < size){//本次任务将处理的数组大小 如果小于指定值则处理数据
for(int i = from;i < to;i++){
if(p.test(values[i])){
count ++;
}
}
return count;
}else{//本次任务将处理的数组大小 如果大于指定值则将任务分为两个小任务
int mind = (to + from)/2;
Counter c1 = new Counter(values, from, mind, p, size);
Counter c2 = new Counter(values, mind, to, p, size);
invokeAll(c1,c2);
return c1.join()+c2.join();
}
}
}
2 新建一个测试类
public class Test{
public static void main(String[] arg){
int SIZE = 100000000;
Random r = new Random();
int[] values = new int[SIZE+1];
for(int i = 0; i < SIZE; i++){//遍历向数组中添加数据
values[i] = r.nextInt(100);
}
long curent = System.currentTimeMillis();
Counter c = new Counter(values, 0, SIZE, e->e>50,1000);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(c);
//输出本次计算大于50的元素个数
System.out.println(c.join());
//输出fork-join框架的计算用时
System.out.println(System.currentTimeMillis() - curent);
long curent2 = System.currentTimeMillis();
int count = 0;
for(int i = 0 ; i<SIZE;i++){
if(values[i]>50){
count++;
}
}
//输出本次计算小于50的元素个数
System.out.println(count);
//输出普通遍历比较计算用时
System.out.println(System.currentTimeMillis() - curent);
}
}
输出结果:
48991268
148
48991268
224
由测试结果可以知道:采用fork-join框架计算用时 少于传统的遍历计算用时