package forkjoin;
import java.util.concurrent.*;
import java.util.stream.LongStream;
public class TestForkJoin {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 使用三种不同的方式从1加到十亿,看那种方式用时短。
// 第一种,单纯地循环累加
test1();
// 第二种,使用ForkJoin的方式
test2();
// 第三种,使用Stream流
test3();
}
private static void test3() {
Long start = System.currentTimeMillis();
// 以下一行代码存疑,不知道为啥这样写。
long sum = LongStream.rangeClosed(1L, 10_0000_0000L).parallel().reduce(0, Long::sum);
Long end = System.currentTimeMillis();
System.out.println("用时" + (end - start) + "毫秒,计算结果为:" + sum);
}
private static void test2() throws ExecutionException, InterruptedException {
ForkJoinPool pool = new ForkJoinPool();
Long start = System.currentTimeMillis();
ForkJoinTask<Long> task = pool.submit(new MyForkJoin(1L, 10_0000_0000L));
Long end = System.currentTimeMillis();
System.out.println("用时" + (end - start) + "毫秒,计算结果为:" + task.get());
}
private static Long test1() {
Long start = System.currentTimeMillis();
Long sum = 0L;
for (Long i = 1L; i <= 10_0000_0000; i++) {
sum += i;
}
Long end = System.currentTimeMillis();
System.out.println("用时" + (end - start) + "毫秒,计算结果为:" + sum);
return sum;
}
}
class MyForkJoin extends RecursiveTask<Long> {
private Long start;
private Long end;
private Long max_sub = 1000L;
public MyForkJoin(Long start, Long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if (end - start <= max_sub) {
Long sum = 0L;
for (Long i = start; i <= end; i++) {
sum += i;
}
return sum;
} else {
Long middle = (start + end) / 2;
MyForkJoin left = new MyForkJoin(start, middle);
MyForkJoin right = new MyForkJoin(middle + 1, end);
left.fork();
right.fork();
return left.join() + right.join();
}
}
}
执行结果:
"C:\Program Files\Java\jdk1.8.0_51\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2020.1\lib\idea_rt.jar=60545:C:\Program Files\JetBrains\IntelliJ IDEA 2020.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_51\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\rt.jar;H:\IdeaProjects\myThreadTest2\out\production\myThreadTest2" forkjoin.TestForkJoin
用时9546毫秒,计算结果为:500000000500000000
用时1毫秒,计算结果为:500000000500000000
用时182毫秒,计算结果为:500000000500000000Process finished with exit code 0
第一个结果意料之中,但是第二给结果挺诧异的。欢迎同行们讨论为啥反而比第二个慢?
另外,使用第一种方法的话,类型改成long而非包装类,会快一个数量级。
参考: