Version: Next

ForkJoin

分支合并——分治法

  • JDK 1.7
  • 并行执行任务,在大数据时提高效率

工作窃取

  • 两个线程,其中一个跑完了自己的代码,另一个跑了一半

  • 跑完的这个线程可以把没跑完的那个的代码偷过来帮他跑了

  • 通过维护双端队列实现

如何使用

  1. 通过ForkJoinPool执行
  2. 调用void execute(ForkJoinTask<?> task)
  3. 定义ForkJoinTask任务,它是一个类
    • 子类:RecusiveAction递归事件,没有返回值
    • 子类:RecusiveTask递归任务,有返回值
  4. 继承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