ForkJoin
什么是ForkJoin 并行执行任务 提高效率(大数据量时)
大数据:MapReduce 把大任务拆分为小任务
ForkJoin
ForkJoin特点 工作窃取 维护了一个双端队列
当两个线程同时执行时,其中一个线程先执行完,可以偷取未执行完线程的工作帮助它执行
ForkJoin操作
定义一个计算类继承 RecursiveTask
/*求和计算*/
public class ForkJoinTest extends RecursiveTask<Long> {
private Long start;
private Long end;
private Long temp=100000L;
public ForkJoinTest(Long start, Long end) {
this.start = start;
this.end = end;
}
//如果小于临界值,就用普通方式,否则使用forkJoin方式
@Override
protected Long compute() {
if(end-start<temp){
//分支合并计算 如何使用forkJoin
/*
* 1. forkJoinPool
* 2. 计算任务,forkJoinPool.execute(ForkJoinTask task)
* 3. 计算类继承 RecursiveTask<Long> 类*/
Long sum=0L;
for(Long i=start;i<=end;i++)
{
sum=sum+i;
}
return sum;
}else{
long middle=(start+end)/2;
ForkJoinTest task1 = new ForkJoinTest(start, middle);
task1.fork(); //拆分任务,把任务压入线程队列
ForkJoinTest task2 = new ForkJoinTest(middle + 1, end);
task2.fork();
return task1.join()+task2.join(); //返回结果
}
}
}
测试类
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
test3();
}
//普通方式
//sum=500000000500000000 时间:3594
public static void test1(){
long sum=0L;
long start=System.currentTimeMillis();
for(Long i=1L;i<=10_0000_0000;i++){
sum=sum+i;
}
long end=System.currentTimeMillis();
System.out.println("sum="+sum+" 时间:"+(end-start));
}
//ForkJoin
//sum=500000000500000000 时间:4256 可以调节
public static void test2() throws ExecutionException, InterruptedException {
long start=System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTest task = new ForkJoinTest(0L, 10_0000_0000L);
//forkJoinPool.execute(task); //执行任务 同步
ForkJoinTask<Long> submit = forkJoinPool.submit(task);//提交任务 异步
Long sum = submit.get();
long end=System.currentTimeMillis();
System.out.println("sum="+sum+" 时间:"+(end-start));
}
//Stream并行流
//sum=500000000500000000 时间:234 最优方案
public static void test3(){
long start=System.currentTimeMillis();
long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0L, Long::sum);
long end=System.currentTimeMillis();
System.out.println("sum="+sum+" 时间:"+(end-start));
}
}
ForkJoin必须是在大数据量时使用