Version: Next
ForkJoin
分支合并——分治法
- JDK 1.7
- 并行执行任务,在大数据时提高效率
工作窃取
两个线程,其中一个跑完了自己的代码,另一个跑了一半
跑完的这个线程可以把没跑完的那个的代码偷过来帮他跑了
通过维护双端队列实现
如何使用
- 通过
ForkJoinPool
执行- 调用
void execute(ForkJoinTask<?> task)
- 定义
ForkJoinTask
任务,它是一个类
- 子类:
RecusiveAction
递归事件,没有返回值- 子类:
RecusiveTask
递归任务,有返回值- 继承
RecusiveTask
,重写compute()
方法
例:求和
低端写法
// 求和计算任务
int sum = 0;
for (int i = 0; i < 10_0000_0000; i++) {
sum += i;
}
System.out.println(sum);
ForkJoin
public class Demo extends RecursiveTask<Long> {
private long start;
private long end;
// 临界值
private long temp = 1_0000L;
public Demo(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 { // 否则分治
long middle = (start + end) / 2; // 中间值
Demo recusiveTask1 = new Demo(start, middle);
Demo recusiveTask2 = new Demo(middle + 1, end);
recusiveTask1.fork(); //拆分任务,将任务压入线程队列
recusiveTask2.fork(); //拆分任务,将任务压入线程队列
// 合并并返回
return recusiveTask1.join() + recusiveTask2.join();
}
}
}
测试
低端方法
public static void test1() {
long start = System.currentTimeMillis();
long sum = 0L;
for (long i = 0L; i < 10_0000_0000; i++) {
sum += i;
}
long end = System.currentTimeMillis();
System.out.println("sum = " + sum + " | 时间:" + (end - start));
}
sum = 499999999500000000 | 时间:302
ForkJoin
public static void test2() throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ForkJoinTask<Long> task = new Demo(0L, 10_0000_0000L);
ForkJoinTask<Long> submit = new ForkJoinPool().submit(task);
long sum = submit.get();
long end = System.currentTimeMillis();
System.out.println("sum = " + sum + " | 时间:" + (end - start));
}
sum = 500000000500000000 | 时间:216
Stream并行流
public static void test3() {
long start = System.currentTimeMillis();
long sum = LongStream.rangeClosed(0L, 10_0000_0000L)
.parallel()
.reduce(0, (a, b) -> Long.sum(a, b));
long end = System.currentTimeMillis();
System.out.println("sum = " + sum + " | 时间:" + (end - start));
}
sum = 500000000500000000 | 时间:214