ForkJoin
什么是 ForkJoin
ForkJoin 在 jdk1.7 之后出现!并行执行任务,用来提高效率,作用在大数据量的情况下!
ForkJoinPool 不是为了替代 ExecutorService,而是它的补充,在某些应用场景下性能比 ExecutorService 更好。
一个线程并发成多个去操作!
ForkJoin 和一个东西很像!
日后要是学习大数据,会学到一个东西:Map Reduce(把大任务拆分成小任务) (了解即可!)
大概图,因为他们的结果还要进行回头汇聚,画图太麻烦,就没画太仔细!
ForkJoin 特点:工作窃取
这里面维护的都是双端队列,从上可以,从下面也可以!
也有一些弊端,因为,他们可能会争抢同一个任务。但是利大于弊!
ForkJoin
代码示例:
package com.zhang.forkjoin;
import java.util.concurrent.RecursiveTask;
/**
* 求和计算的任务!
* 小代码看工资 3000 6000(ForkJoin) 9000(Stream并行流)
* 如何使用ForkJoin
* 1、forkjoinPool 通过它来执行
* 2、计算任务 forkjoinPooL.execute (ForkJoinTask task)
* 3、计算机要继承 RecursiveTask
*/
public class ForkJoinDemo extends RecursiveTask<Long> {
private Long start; // 1
private Long end; // 99999999
//临界值(超过这个值会分成两个任务)
private Long temp = 10000L;
public ForkJoinDemo(Long start, Long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if((end-start)<temp){
Long sum = 0L;
for (Long i = start; i < end; i++) {
sum += i;
}
return sum;
}else{ // 分支合并计算 forkjoin
long mid = (start + end) / 2; //中间值!
ForkJoinDemo task1 = new ForkJoinDemo(start, mid);
ForkJoinDemo task2 = new ForkJoinDemo(mid+1, end);
task1.fork(); //拆分任务,把任务压入线程队列!
task2.fork();
return task1.join()+task2.join();
}
}
}
测试类:
package com.zhang.forkjoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
/**
* 同一个任务,别人效率快你几十倍!
*/
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// test1(); //耗时 5226
// test2(); //耗时 4190
test3(); //耗时 160
}
// 3000
public static void test1(){
Long sum = 0L;
long start = System.currentTimeMillis();
for (Long i = 1L; i <= 10_0000_0000; i++) {
sum += i;
}
long end = System.currentTimeMillis();
System.out.println("sum="+sum+",时间:"+(end-start));
}
//会使用forkjoin 6000
public static void test2() throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinDemo(0L, 10_0000_0000L);
ForkJoinTask<Long> submit = forkJoinPool.submit(task);//提交任务!
Long sum = submit.get();
long end = System.currentTimeMillis();
System.out.println("sum="+sum+"时间:"+(end-start));
}
//9000 Stream并行流
public static void test3(){
long start = System.currentTimeMillis();
//Stream并行流
long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long::sum);
long end = System.currentTimeMillis();
System.out.println("sum="+sum+"时间:"+(end-start));
}
}