一、概述
forkjion里面的两个重要的概念
分而治之,什么是分而治之?
一个大的事情平均分成几个相同小的事情,如果没有达到最小的要求,就继续分,一直分到达到的要求。
工作密取,workStealing
如果分而治之的线程很多,就会形成线程的队列,这里面就会有完成的快和慢的不同线程。快的线程执行完成以后,就会把慢的队列拿过来进行执行。
二、代码实现
//计算长度为ARRAY_LENGTH 数组中的数值总和
public class TestForkJoin {
//数组长度
public static final int ARRAY_LENGTH = 100000000;
public static class MyTask extends RecursiveTask<Integer>{
private final static int THRESHOLD = MakeArray.ARRAY_LENGTH/10;
private int[] src; //表示我们要实际统计的数组
private int fromIndex;//开始统计的下标
private int toIndex;//统计到哪里结束的下标
MyTask(int[] src, int fromIndex, int toIndex){
this.src = src;
this.fromIndex = fromIndex;
this.toIndex = toIndex;
}
@Override
protected Integer compute() {
if(toIndex - fromIndex < THRESHOLD){
int count = 0;
for (int i = fromIndex; i <= toIndex ; i++) {
count = count + src[i];
}
return count;
}else{
int mid = (fromIndex + toIndex) / 2;
MyTask left = new MyTask(src,fromIndex,mid);
MyTask right = new MyTask(src,mid+1,toIndex);
invokeAll(left,right);
return left.join()+right.join();
}
}
public static void main(String[] args) {
//使用forkJoin
ForkJoinPool forkJoinPool = new ForkJoinPool();
int[] src = makeArray();
MyTask myTask = new MyTask(src,0,src.length-1);
long currentTimeMillis = System.currentTimeMillis();
Integer invoke = forkJoinPool.invoke(myTask);
System.out.println("forkjoin结果是: "+invoke+" 耗时:"+(System.currentTimeMillis() - currentTimeMillis)+"毫秒");
//使用普通遍历求和
long start = System.currentTimeMillis();
int sum= 0;
for(int i= 0;i<src.length;i++){
sum = sum + src[i];
}
System.out.println("普通遍历结果是: "+sum
+" 耗时:"+(System.currentTimeMillis()-start)+"毫秒");
}
//创建随机数数组
public static int[] makeArray() {
//new一个随机数发生器
Random r = new Random();
int[] result = new int[ARRAY_LENGTH];
for(int i=0;i<ARRAY_LENGTH;i++){
//用随机数填充数组
result[i] = r.nextInt(ARRAY_LENGTH*3);
}
return result;
}
}
}
运行结果:当数组长度比较大的时候,使用forkjoin总是比普通遍历求和要快
forkjoin结果是: -872683364 耗时:45毫秒
普通便利结果是: -872683364 耗时:58毫秒
Process finished with exit code 0