ForkJoin和Stream流的使用

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毫秒,计算结果为:500000000500000000

Process finished with exit code 0

第一个结果意料之中,但是第二给结果挺诧异的。欢迎同行们讨论为啥反而比第二个慢?

另外,使用第一种方法的话,类型改成long而非包装类,会快一个数量级。

参考:

【狂神说Java】JUC并发编程最新版通俗易懂_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值