ForkJoin :: 分支合并 (JDK 1.7)
-
并行执行任务,提高效率。
-
使用场景:大数据量
-
将大任务拆成小任务
ForkJoin 特点:工作窃取
这个里面维护的都是双端队列,如果一方执行完了,获取另外一方的未完成的任务进行执行
ForkJoin 的操作
package pers.vincent.matrix.subject.forkjoin;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
public class ForkJoinDemp extends RecursiveTask<Long> {
private Long start;
private Long end;
private Long temp = 10_0000L;
public ForkJoinDemp(Long start, Long end){
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if((end-start) <= temp){
Long result = 0L;
for (Long i = start; i <= end; i++) {
result += i;
}
return result;
}else{
Long middle = (end + start) / 2;
ForkJoinDemp task1 = new ForkJoinDemp(start, middle);
task1.fork();
ForkJoinDemp task2 = new ForkJoinDemp(middle+1, end);
task2.fork();
return task1.join() + task2.join();
}
}
}
测试代码:(普通 - ForkJoin - Stream 流计算)
package pers.vincent.matrix.subject.forkjoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
public class Test1 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start = 0L;
long end = 10_0000_0000L;
test3(start, end);
}
/**
* TOTAL TIME = 5699
* @param start
* @param end
*/
public static void test1(Long start, Long end){
long beginTime = System.currentTimeMillis();
Long result = start;
for (Long i = 0L; i <=end; i++) {
result += i;
}
long endTime = System.currentTimeMillis();
System.out.println("Time===" + (endTime-beginTime) + ", result = " + result);
}
/**
* TOTAL TIME : 4908
* @param start
* @param end
* @throws ExecutionException
* @throws InterruptedException
*/
public static void test2(Long start, Long end) throws ExecutionException, InterruptedException {
long beginTime = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> forkJoinDemp = new ForkJoinDemp(start, end);
ForkJoinTask<Long> sum = forkJoinPool.submit(forkJoinDemp);
long result = sum.get();
long endTime = System.currentTimeMillis();
System.out.println("Time===" + (endTime-beginTime) + result);
}
/**
* TOTAL TIME = 250
* @param start
* @param end
*/
public static void test3(Long start, Long end){
long beginTime = System.currentTimeMillis();
long sum = LongStream.rangeClosed(start, end).parallel().reduce(0, Long::sum);
long endTime = System.currentTimeMillis();
System.out.println("Time===" + (endTime-beginTime) + ", result = " + sum);
}
}