资讯专栏INFORMATION COLUMN

「Java 8 函数式编程」读书笔记——数据并行化

leone / 1306人阅读

摘要:限制编写并行流,存在一些与非并行流不一样的约定。底层框架并行流在底层沿用的框架,递归式的分解问题,然后每段并行执行,最终由合并结果,返回最后的值。

本书第六章的读书笔记,也是我这个系列的最后一篇读书笔记。后面7、8、9章分别讲的“测试、调试与重构”、“设计和架构的原则”以及“使用Lambda表达式编写并发程序”,因为笔记不好整理,就不写了,感兴趣的同学自己买书来看吧。

并行化流操作

关于并行并发的区别和并行的重要性的讨论这里不做笔记了,直接看Stream类库提供了哪些关于并行的操作把。

如果已经有了一个Stream对象,可以调用parallel方法使其拥有并行操作的能力;

如果想从一个集合类创建一个Stream对象,可以调用parallelStream方法获得一个拥有并行能力的流。

BaseStream提供的sequential方法将会按顺序遍历Stream中的元素

对于同一个Stream对象,如果parallel方法和sequential方法都被调用,最后调用的那个方法将起效,不能同时处于两种模式。

使用并行流,不需要写代码用于处理调度和等待线程池中的某项任务完成,这些工作都交由类库完成。

限制

编写并行流,存在一些与非并行流不一样的约定。

reduce方法的限制 初值必须为组合函数的恒等值

使用恒等值与其他值做reduce运算时,其他值保持不变。比如,使用reduce进行求和运算时,初值必须为0,而进行求积运算时,初值必须为1

reduce操作必须符合结合律

因为并行计算时,元素的遍历顺序是不确定的,所以只有符合结合律才能保证结果是确定的。

避免持有锁

前面提到过,并行流的操作,是把线程的调度等工作交给了类库解决的,所以不要做持有锁的操作,否则是自找麻烦

性能 主要影响因素

影响并行流的性能的因素主要有5个:

数据大小

因为并行处理会带来分解数据和合并数据的额外开销,所以只有当数据量足够大时使用并行流操作才具有意义,否则就是在浪费资源。

源数据结构

源数据通常是集合,而因为具体的类型不同,造成了分割时的开销不同。

装箱

基本数据类型比装箱类型处理更快。

核的数量

拥有的核数量越多,潜在的性能提升越大。但这里的核是指运行时进程能够使用的核的数量。

单元处理开销

花在每个元素上的处理时间越长,并行带来的性能提升越大。

底层框架

并行流在底层沿用的fork/join框架,fork递归式的分解问题,然后每段并行执行,最终由join合并结果,返回最后的值。

数据结构分解的难易

数据结构对半分解的难易程度,决定了分解的效率。可以将核心类库提供的通用数据结构分为三类:

性能好

ArrayList数组或者IntStream.range这样的支持随机读取的结构,能够轻易的分解。

性能一般

HashSetTreeSet这样的数据结构不易公平的分解。

性能差

有的数据结构难于分解,有的结构可能需要花O(N)的时间复杂度来分解。比如:LinkedList,难以对半分解;Streams.iterateBufferedRead.lines这样长度未知的数据结构也难以分解。

操作的状态

流中的操作,可以分为有状态无状态。无状态的操作在整个操作中不必维护状态;有状态的操作则有维护状态所需的开销和限制。

避开有状态的操作,可以获得更好的并行性能。无状态的操作包括mapfilterflatMap;有状态的操作包括sorteddistinctlimit

并行化数组操作

Java 8为数组提供了并行化操作的方法,这些方法在Arrays类中:

method description
parallelPrefix 任意给定一个函数,计算数组的“和”(任意BinaryOperator
parallelSetAll 使用Lambda表达式更新数组元素
parallelSort 并行化对数组元素排序

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66672.html

相关文章

  • java 8 实战》读书笔记 -第十四章 函数编程的技巧

    摘要:但是,最好使用差异化的类型定义,函数签名如下其实二者说的是同一件事。后者的返回值和初始函数的返回值相同,即。破坏式更新和函数式更新的比较三的延迟计算的设计者们在将引入时采取了比较特殊的方式。四匹配模式语言中暂时并未提供这一特性,略。 一、无处不在的函数 一等函数:能够像普通变量一样使用的函数称为一等函数(first-class function)通过::操作符,你可以创建一个方法引用,...

    nemo 评论0 收藏0
  • java 8 实战》读书笔记 -第四章 引入流

    摘要:第四章引入流一什么是流流是的新成员,它允许你以声明性方式处理数据集合通过查询语句来表达,而不是临时编写一个实现。 第四章 引入流 一、什么是流 流是Java API的新成员,它允许你以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现)。就现在来说,你可以把它们看成遍历数据集的高级迭代器。此外,流还可以透明地并行处理,你无需写任何多线程代码。 下面两段代码都是用来返回低...

    jeyhan 评论0 收藏0
  • Java8实战》-第四章读书笔记(引入流Stream)

    摘要:内部迭代与使用迭代器显式迭代的集合不同,流的迭代操作是在背后进行的。流只能遍历一次请注意,和迭代器类似,流只能遍历一次。 流(Stream) 流是什么 流是Java API的新成员,它允许你以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现)。就现在来说,你可以把它们看成遍历数据集的高级迭代器。此外,流还可以透明地并行处理,你无需写任何多线程代码了!我会在后面的笔记中...

    _ivan 评论0 收藏0
  • Java8新特性总览

    摘要:新特性总览标签本文主要介绍的新特性,包括表达式方法引用流默认方法组合式异步编程新的时间,等等各个方面。还有对应的和类型的函数连接字符串广义的归约汇总起始值,映射方法,二元结合二元结合。使用并行流时要注意避免共享可变状态。 Java8新特性总览 标签: java [TOC] 本文主要介绍 Java 8 的新特性,包括 Lambda 表达式、方法引用、流(Stream API)、默认方...

    mayaohua 评论0 收藏0
  • Java 8 函数编程读书笔记——流

    摘要:本文是函数式编程第三章的读书笔记,章名为流。正确使用表达式明确要达成什么转化,而不是说明如何转化没有副作用只通过函数的返回值就能充分理解函数的全部作用函数不会修改程序或外界的状态获取值而不是变量避免使用数组逃过的追杀,应该考虑优化逻辑 本文是「Java 8 函数式编程」第三章的读书笔记,章名为流。本章主要介绍了外部迭代与内部迭代以及常用的高阶函数。 外部迭代与内部迭代 外部迭代 过去我...

    qpwoeiru96 评论0 收藏0

发表评论

0条评论

leone

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<