Jdk8的parallelStream的执行者是谁

一、前言

原文链接:https://mp.weixin.qq.com/s/_e9kRwNYggNDOz9BR8J-JQ

jdk8的parallelStream的执行线程是谁,你知道吗?

我们都知道 parallelStream 是并行流,相较stream而言,可以充分利用cpu资源,加快运行算速度。但是却从未探究过他的执行线程是谁这类问题。今天一起分析下。

二、验证与分析

1、先看一段普通程序:

    public static void main(String[] args) {
        List<Integer> nums = Arrays.asList(4, 1, 55, 49);
        nums.parallelStream().forEach(System.out::println);// 输出上面数据
    }

运行结果:因为是多线程运行,所以输出结果顺序与输入结果不一致。的确是并行执行的。

55
49
4
1

2、看看他的执行线程:

    public static void main(String[] args) {
        List<Integer> nums = Arrays.asList(4, 1, 55, 49);
        nums.parallelStream().forEach(r ->
                System.out.println(Thread.currentThread().getName() + "\t" + r)
        );
    }

运行结果:可以看到不仅使用了ForkJoinPool线程池里的线程,也使用了main线程。为什么呢?

main    55
ForkJoinPool.commonPool-worker-2    49
ForkJoinPool.commonPool-worker-1    1
main    4

引用《java 8 实战》的一段话:

并行流内部使用了默认的ForkJoinPool(7.2节会进一步讲到分支/合并框架),它默认的线程数量就是你的处理器数量,这个值是由Runtime.getRuntime().available- Processors()得到的。 但是你可以通过系统属性java.util.concurrent.ForkJoinPool.common. parallelism来改变线程池大小,如下所示: System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism","12"); 这是一个全局设置,因此它将影响代码中所有的并行流。反过来说,目前还无法专为某个 并行流指定这个值。一般而言,让ForkJoinPool的大小等于处理器数量是个不错的默认值, 除非你有很好的理由,否则我们强烈建议你不要修改它。

3、验证ForkJoinPool线程池

从ForkJoinPool类的无参构造中可以看出来,他的默认线程数量等于cpu核心数。

单独设置一下线程数:

    public static void main(String[] args) {
        // 单独设置ForkJoinPool线程数量
        System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "1");
        List<Integer> nums = Arrays.asList(4, 1, 55, 49);
        nums.parallelStream().forEach(r -> {
            System.out.println(Thread.currentThread().getName() + "\t" + r);
        });
    }

结果分析:可以看到生效了,因为处理多个任务时候,ForkJoinPool线程池中只拿出了1个线程来执行。线程池的容量为1。

其实也可以通过输出System.out.println(ForkJoinPool.commonPool().getPoolSize());查看线程池大小是否生效

main    55
ForkJoinPool.commonPool-worker-1    1
main    49
ForkJoinPool.commonPool-worker-1    4

三、总结

  • parallelStream()默认线程池是ForkJoinPool线程池。

  • parallelStream() 执行程序的时候,并非都使用ForkJoinPool线程池里的线程来完成工作,也会使用其调用线程(eg:main线程)。

  • 在高并发场景,如果某个耗时的接口中使用了并行流。执行业务逻辑的线程可以是来自容器的线程(eg;tomcat),会加速消耗容器线程,也会加速cpu与内存的消耗,严重的话可能导致系统崩溃。因此在使用时需要注意此类场景。

  • ForkJoinPool线程池的默认线程数是cpu核心数(Runtime.getRuntime().availableProcessors()

获取更多内容,请关注微信公众号。搜索“码圈小橙子,这里会不时的更新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值