14.1、什么是ForkJoin
ForkJoin在 JDK1.7 之后出现,并行执行任务! 提高效率,大数据量!
大数据:Map Reduce(把大任务拆分成小任务)
13.2、ForkJoin 特点
工作窃取
这个里面维护的都是双端队列
现有两个线程A、B,此时B线程已经执行完了,A还没有执行完,这时B就会将A里面的任务偷过来执行。
13.3、ForkJoin操作
ForkJoinDemo:
package com.chen.forkjoin;
import java.util.concurrent.RecursiveTask;
/**
* 求和计算的任务
*
* 如何使用ForkJoin?
* 1、ForkJoinPool 通过它来执行
* 2、计算任务 forkJoinPool.execute(ForkJoinTask<?> task)
* 3、计算类要继承FastJoinTask
*/
public class ForkJoinDemo extends RecursiveTask<Long> {
private Long start; // 1
private Long end; // 1990900000
// 临界值
private Long temp = 10000L;
public ForkJoinDemo(Long start, Long end) {
this.start = start;
this.end = end;
}
public static void main(String[] args) {
}
@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 middle = (start + end) / 2;
ForkJoinDemo task1 = new ForkJoinDemo(start, middle);
task1.fork(); // 拆分任务,把任务压入线程队列
ForkJoinDemo task2 = new ForkJoinDemo(middle + 1, end);
task2.fork(); // 拆分任务,把任务压入线程队列
return task1.join() + task2.join();
}
}
}
测试:
package com.chen.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(); // 耗费时间:20120
// test2(); // 耗费时间:15189
test3(); // 耗费时间:233
}
// 普通程序员
public static void test1(){
long start = System.currentTimeMillis();
Long sum = 0L;
for (Long i = 1L; i <= 10_0000_0000; i++) {
sum += i;
}
long end = System.currentTimeMillis();
System.out.println("sum="+ sum +"时间:"+(end - start));
}
// 会使用ForkJoin
public static void test2() throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinDemo 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));
}
public static void test3(){
long start = System.currentTimeMillis();
// Stream 并行流
// range():()
// rangeClosed():(]
long sum = LongStream.rangeClosed(0L, 10_0000_0000).parallel().reduce(0, Long::sum);
long end = System.currentTimeMillis();
System.out.println("sum=" + sum + "时间:"+(end - start));
}
}