计算1-100亿累加值,并和单线程效率比较
一、ForkJoinCalculation核心类
import java.util.concurrent.RecursiveTask;
/**
* @ClassName: ForkJoinCalculation
* @Description: TODO
* @author Liu
* @date 2021年3月8日 上午8:00:14
*/
public class ForkJoinCalculation extends RecursiveTask<Long>{//RecursiveAction<Long>不返回结果
private Long start;
private Long end;
//临界值
private static final Long THRESHOLD = 10000L;
public ForkJoinCalculation(Long start, Long end) {
super();
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long length = end - start;
if(length <= THRESHOLD) {
long sum = 0;
for (long i = start; i <= end; i++) {
sum += i;
}
return sum;
}
else {
long mid = ( start + end ) / 2;
ForkJoinCalculation left = new ForkJoinCalculation(start, mid);
left.fork();//拆分子任务,同时压入线程队列
ForkJoinCalculation right = new ForkJoinCalculation(mid + 1, end);
right.fork();
return left.join() + right.join();
}
}
}
二、测试
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
import org.junit.Test;
/**
* @ClassName: ForkJoinTest
* @Description: TODO
* @author Liu
* @date 2021年3月8日 上午8:17:46
*/
public class ForkJoinTest {
/***
* ForkJoin框架
*/
@Test
public void test() {
Instant start = Instant.now();
ForkJoinPool pool = new ForkJoinPool();
//4229(100亿)-27295(500亿)
ForkJoinTask<Long> task = new ForkJoinCalculation(1L, 50000000000L);
long sum = pool.invoke(task);
System.out.println(sum);
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis());
}
/***
* 普通for
*/
@Test
public void test2() {
Instant start = Instant.now();
long sum = 0;
for (long i = 0; i <= 50000000000L; i++) {
sum += i;
}
System.out.println(sum);
Instant end = Instant.now();
//3391(100亿)-16869(500亿)
System.out.println(Duration.between(start, end).toMillis());
}
/**
* java8并行流
*/
@Test
public void test3() {
Instant start = Instant.now();
long reduce = LongStream.rangeClosed(0, 50000000000L)
.reduce(0, Long :: sum);
System.out.println(reduce);
Instant end = Instant.now();
//27629(500亿)
System.out.println(Duration.between(start, end).toMillis());
}
}
三、总结
1、在数字较小范围内(如1亿),和单线程相比,可能比单线程慢;
2、ForkJoin框架发挥作用,数字要足够大,另一个是临界值THRESHOLD要合理(偏大);
3、重视parallel()-map-reduce处理大数据量的优势。