java8的并行Stream对开发者非常友好,非常容易实现并行计算。并行Stream底层使用ForkJoinTask实现Stream的并行处理,充分利用cpu的多核能力,Stream的API将底层复杂实现完全屏蔽了,开发者仅需调用一个方法即可实现并行计算,就是这么简单。

开启并行Stream

开启并行Stream只需在调用终止操作符之前调用parallel()方法即可开启并行计算。

    @Test    public void parallelStream(){        IntStream.range(0,100)                .parallel()                .forEach(e-> System.out.println(Thread.currentThread()+" "+e));    }

执行上述代码,可以看出代码将会交由ForkJoinPool中的线程执行。

小试牛刀

这里使用分别使用并行Stream和穿行Stream计算0到100000000000之间的和

    @Test    public void testSum(){        //并行计算        long time= System.currentTimeMillis();        long sum1 = LongStream.rangeClosed(1,100000000000l).parallel().sum();        System.out.println(System.currentTimeMillis()-time);        //串行计算        time = System.currentTimeMillis();        long sum2 = LongStream.rangeClosed(1,100000000000l).sum();        System.out.println(System.currentTimeMillis()-time);        System.out.println("sum1 = "+sum1+" sum2 = "+sum2);        Assert.assertTrue(sum1==sum2);    }

执行结果如图,我的cpu是6核的,串行计算的时间差不多是并行计算的5倍;并行计算下充分利用了cpu的多核性能,如果数据量更大,两者之间的差距更大,并行Stream的优势更加明显。

sequential()和parallel()

默认情况下创建的stream都是串行的,parallel将串行流转成并行流,两者是互斥冲突的,sequential将并行流转成串行流,但并不意味者二者不可同时出现。

isParallel()可以检测stream是否为并行stream。

    @Test    public void isParallel(){        IntStream stream = IntStream.range(0,100);        stream.parallel();        Assert.assertTrue(stream.isParallel());    }

如代码所示,执行‘串行->并行->串行->并行’的转换,最终还是并行流。

    @Test    public void spspIsP(){        IntStream stream = IntStream.range(0,100);        stream.parallel().map(e->e<<1).sequential().parallel();        Assert.assertTrue(stream.isParallel());    }

如代码所示,执行‘串行->并行->串行’的转换,最终还是串行流。

    @Test    public void spsIsS(){        IntStream stream = IntStream.range(0,100);        stream.parallel().map(e->e<<1).sequential();        Assert.assertFalse(stream.isParallel());    }

上例子说明,流的串行和并行取决于最后调用的那个方法(sequential() or parallel())。

ForkJoinPool

并行stream底层依赖于ForkJoinPool.commonPool线程池,这是一个jvm进程全局共享的线程,当这个线程池中执行了耗时操作,后面的任务将会堆积,造成性能问题;默认情况下这个线程池的大小为逻辑核数-1,当然你也可以通过jvm参数‘java.util.concurrent.ForkJoinPool.common.parallelism’来修改线程的池大小,这里并不建议使用这种方式,最好的方式是使用自定义的线程池。

如代码所示,创建4线程的ForkJoinPool线程池。

    @Test    public void CustomPool(){        ForkJoinPool forkJoinPool = new ForkJoinPool(4);        forkJoinPool.submit(()->{            IntStream.range(0,100).parallel().forEach(e-> System.out.println(Thread.currentThread()+" "+e));        }).join();    }

代码执行结果如图,并行的stream在自定义的线程池中执行。

那为什么forkJoinPool.submit()就可以实现自定义线程池呢?查看源码得知,ForkJoinWorkerThread内部会持有ForkJoinPool的引用,在代码执行时,最终会调用doInvoke方法,通过Thread.currentThread可以知道是ForkJoinWorkerThread类型的线程,进而获取到ForkJoinPool,最终利用这个pool来执行计算。

     /**     * Implementation for invoke, quietlyInvoke.     *     * @return status upon completion     */    private int doInvoke() {        int s; Thread t; ForkJoinWorkerThread wt;        return (s = doExec()) < 0 ? s :            ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?            (wt = (ForkJoinWorkerThread)t).pool.            awaitJoin(wt.workQueue, this, 0L) :            externalAwaitDone();    }

总结

并行Stream给开发者带来了极大的便利,一行代码即可开启多线程并行计算,excellent!但是并行计算也要在一定条件下才能使用,比如任务之间不能有依赖、不能存在竞态条件等。

adobe stream的最后一行空行_玩转Java8Stream(五、并行Stream)相关推荐

  1. adobe stream的最后一行空行_Excel VBA 7.66 如何快速删除数据间空行?手动慢又乱!VBA快又准...

    前景提要(文末提供源码下载) 其实不管是做数据处理还是数据分析,都并不算是很困难的事情,只要数据标准,分析出我们想要的结果那也是分分钟的事情,就算是数据大点,我多花点时间也能得到我们想要的结果,怕就怕 ...

  2. 5单个编译总会编译全部_玩转Android10(五)源码编译开发中常用命令

    源码开发编译中,熟练掌握常用命令,可以提高开发工作效率.Android源码中,将相关的命令分为如下几类: 1.初始化源码编译环境 初始化编译环境,为后续提供如lunch.make.xxgrep.god ...

  3. Python 解决写入csv中间隔一行空行问题

    转载解决写入csv中间隔一行空行问题 写入csv: with open(birth_weight_file,'w') as f:writer=csv.writer(f)writer.writerow( ...

  4. body标签下莫名奇妙多了一行空行,原来是编码的问题

    之前为了方便,直接在服务器修改文件,然后点保存,但是问题来了,在顶部莫名奇妙多了一个空行,如图1 图1 原来在源代码编辑的代码如图2 图2 但是在FF或者Chrome外部样式却在body里面,而不是h ...

  5. 玩转Java8中的 Stream 之从零认识 Stream

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:litesky www.jianshu.com/p/11c9 ...

  6. java stream 取不同的数据_基础篇:JAVA.Stream函数,优雅的数据流操作

    前言 平时操作集合数据,我们一般都是for或者iterator去遍历,不是很好看.java提供了Stream的概念,它可以让我们把集合数据当做一个个元素在处理,并且提供多线程模式 流的创建 流的各种数 ...

  7. Java8 Stream:20+实际例子,玩转集合的筛选、归约、分组、聚合

    来源: https://blog.csdn.net/mu_wind/article/details/109516995 Java8中的stream,可大幅提升咱们的开发效率,带大家看下stream到底 ...

  8. 玩知乎五年,我赚了多少钱?

    大家好,我是张小方.小方是一位知乎老鸟,玩了快五年知乎,上个月知乎粉丝终于突破一万了,惊喜得我不知所措呀. 不止一个读者在问我:小方老师现在也是知乎万粉大 V 了,知乎如此多的关注.点赞,加上付费咨询 ...

  9. 解决 HTTP/2 stream 1 was not closed cleanly before end of the underlying stream

    使用 git 的时候发现一直提示 HTTP/2 stream 1 was not closed cleanly before end of the underlying stream. 通过排查发现, ...

最新文章

  1. 给char*一个名份
  2. C# 图片识别(支持21种语言)
  3. Java讲课笔记05:运算符与表达式
  4. 一次 Java 内存泄漏排查过程,涨姿势
  5. Runloop与autoreleasePool联系
  6. 推荐几个前端模板下载站
  7. YYText-swift,swift版的YYText,优化了yylabel和yytextview的部分扩展
  8. 计算机电脑配置ppt,计算机应用基础之word2010课件.ppt
  9. 金融学习之四——插值法求远期国债收益率
  10. html语言加号点一下变成减号6,CSS3 linear-gradient线性渐变生成加号和减号的方法...
  11. nisp和cisp证书有什么区别
  12. Java多线程探究-死锁原因
  13. 信奥学习规划 信息学竞赛之路(2022.07.31)
  14. ndarray数组的操作和运算
  15. 华为认证--云计算HCIA-2
  16. 北京大学计算机学院,官宣首任院长
  17. 【弄nèng - Activiti6】Activiti6入门篇(十六)—— 信号中间事件
  18. MT5 EA交易期货-市价单开仓平仓
  19. 常用网络安全问题排查命令总结
  20. Android消息推送叨逼叨

热门文章

  1. Java快速开发框架LML简介
  2. 使用 IAsyncResult 进行 .NET 异步编程
  3. 吐血原创-我用“电驴”抓肉鸡!!!
  4. html 方式使用iview,VUE之iview框架使用教程
  5. mysql建立索引 有什么缺陷_MySQL数据库建立索引的优缺点以及什么样的字段适合建立索引...
  6. ajax提交前先验证,jQuery验证AJAX之前提交(jQuery validation before AJAX sub
  7. 信息学奥赛一本通(1094:与7无关的数)
  8. 信息学奥赛一本通(1054:三角形判断)
  9. 38 SD配置-销售凭证设置-定义拒绝原因
  10. 37 CO配置-控制-产品成本控制-成本对象控制-实际成本核算/物料分类帐-分配货币类型并定义物料分类账类型