写点什么

解析 Stream foreach 源码

  • 2022 年 9 月 15 日
    中国香港
  • 本文字数:1017 字

    阅读完需:约 3 分钟

解析Stream foreach源码

本文分享自华为云社区《深入理解Stream之foreach源码解析》,作者:李哥技术 。

前言


前面在深入理解 Stream 之原理剖析中提到,Stream 中的操作可以分为两大类:中间操作与结束操作。


今天要说的 foreach 是属于结束操作。


Stream 流操作从并发上来分类,又可以分为并行流和串行流,今天就来刨根问底的看看吧。

foreach 串行流







foreach 并行流








从目前来看,parallelStream(并行流)与 stream(串行流)的区别仅仅是一个变量而已。别着急,让我们继续往下看。





记住这里的 ordered 是 false,因为是并行流,不可能是有序遍历。continue。






我们来简单分析一下 ForEachTask 类,它继承于 CountedCompleter。


static final class ForEachTask<S, T> extends CountedCompleter<Void> {}
复制代码












最后这里使用 ForkJoin 框架,利用分治法的思想,将一个大任务拆分很多个小任务去执行,最后一一汇总到大任务。


我们一路过五关斩六将,终于将它给挖穿了。不容易啊。

总结


我们简单回顾总结一下:


对于串行流:


  1. 先得到 ReferencePipeline.Head 的 Stream 实现类,内部有一个拆分器,值是一个 ArrayListSpliterator 对象;

  2. 对于并行流,当前线程直接调用 ArrayListSpliterator 对象的 forEachRemaining 方法。


对于并行流:


  1. 先得到 ReferencePipeline.Head 的 Stream 实现类,内部有一个拆分器,值是一个 ArrayListSpliterator 对象;

  2. 迭代的时候调用父类的 forEach 方法;

  3. 构建一个 ForEachTask,当前线程继续执行 invoke 方法;

  4. 最终执行 java.util.stream.ForEachOps.ForEachTask#compute 方法,使用 ForkJoin 框架,利用 commomPool、ForkJoin 框架分治法的思想,使用拆分器将任务拆分成不同子任务执行;

  5. 对于每一个子任务都会拆分到不能再拆分为止,然后调用 java.util.stream.AbstractPipeline#copyInto 方法,在内部会调用不可再拆分的拆分器的 forEachRemaining 方法,最终调用回调用户方法 action.accept(e);


串行流比较简单,对于 parallelStream,站在它背后的男人是 ForkJoin 框架


ForkJoin 框架是从 jdk7 中新特性,它同 ThreadPoolExecutor 一样,也实现了 Executor 和 ExecutorService 接口。ForkJoinPool 主要用来使用分治法(Divide-and-Conquer Algorithm)来解决问题。Java 8 为 ForkJoinPool 添加了一个通用线程池:commonPool,这个线程池用来处理那些没有被显式提交到任何线程池的任务。它是 ForkJoinPool 类型上的一个静态元素,它拥有的默认线程数量等于运行计算机上的处理器数量。所以,我们的并行流就是使用的这个公共池中的线程来执行的。


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 3
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
解析Stream foreach源码_Java_华为云开发者联盟_InfoQ写作社区