計算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處理大數據量的優勢。