java的Fork-Join分治编程效率问题
解决方法:
结论:计算1-100000000的和同样的计算结果,但Fork-Join分治编程明显效率比较低,消耗时间比较长。如果计算1-400之间的和,那么两个效率一样。如果计算1-400之间的和且加上一个内嵌套for循环1000000000次,这时,分治编程就可以大大的减少消耗时间。由此可见,分治编程不适合循环次数多的情况,因为循环次数多个话,就会创建很多MyRecursiveTask 对象,很耗内存,所以个人觉得分治编程分治的次数时要根据自己业务代码的消耗时间来确定。一般来说分治编程适合循环次数少,但循环中代码体耗时长的场景下。测试如下所示:
假如我现在想循环统计1-100000000的数据之和。
1.循环100000000次的情况比较
public static void main(String[] args) throws InterruptedException, ExecutionException {
int sum=0;
long begin=System.currentTimeMillis();
for(int i=0;i<=100000000;i++){
sum+=i;
}
System.out.println(sum);
System.out.println(System.currentTimeMillis()-begin);
//Fork-Join分治编程,循环100000000次,循环体不耗时的情况
long begin2=System.currentTimeMillis();
MyRecursiveTask myRecursiveTask = new MyRecursiveTask(0,100000000);
ForkJoinPool pool=new ForkJoinPool();
pool.execute(myRecursiveTask);
System.out.println("结果值:"+myRecursiveTask.get());
System.out.println("消耗时间:"+(System.currentTimeMillis()-begin2));
}
结果值:987459712
消耗时间:78
结果值:987459712
消耗时间:8860
2.循环400次,再嵌套循环1000000000次的情况比较
public static void main(String[] args) throws InterruptedException, ExecutionException {
long begin=System.currentTimeMillis();
int sum=0;
for(int i=0;i<=400;i++){
sum+=i;
for(int j=0;j<=1000000000;j++){
}
}
System.out.println("结果值:"+sum);
System.out.println("消耗时间:"+(System.currentTimeMillis()-begin));
//Fork-Join分治编程,循环100000000次,循环体不耗时的情况
long begin2=System.currentTimeMillis();
MyRecursiveTask myRecursiveTask = new MyRecursiveTask(0,400);
ForkJoinPool pool=new ForkJoinPool();
pool.execute(myRecursiveTask);
System.out.println("结果值:"+myRecursiveTask.get());
System.out.println("消耗时间:"+(System.currentTimeMillis()-begin2));
}
修改MyRecursiveTask的循环体
protected Integer compute() {
if((end-begin)!=0){
int min=(begin+end)/2;
MyRecursiveTask myRecursiveTaskLeft = new MyRecursiveTask(begin,min);
MyRecursiveTask myRecursiveTaskRight = new MyRecursiveTask(min+1,end);
this.invokeAll(myRecursiveTaskLeft,myRecursiveTaskRight);
int left=myRecursiveTaskLeft.join();
int right=myRecursiveTaskRight.join();
for(int j=0;j<=1000000000;j++){
}
return left+right;
}else{
return end;
}
}
结果值:80200
消耗时间:156148
结果值:80200
消耗时间:81535
MyRecursiveTask 源码:
public class MyRecursiveTask extends RecursiveTask<Integer>{
private int begin;
private int end;
public MyRecursiveTask(int begin, int end) {
super();
this.begin = begin;
this.end = end;
}
@Override
protected Integer compute() {
if((end-begin)!=0){
int min=(begin+end)/2;
MyRecursiveTask myRecursiveTaskLeft = new MyRecursiveTask(begin,min);
MyRecursiveTask myRecursiveTaskRight = new MyRecursiveTask(min+1,end);
this.invokeAll(myRecursiveTaskLeft,myRecursiveTaskRight);
int left=myRecursiveTaskLeft.join();
int right=myRecursiveTaskRight.join();
return left+right;
}else{
return end;
}
}
}
本文链接:http://www.yayihouse.com/yayishuwu/chapter/1500