JAVA8-并行数据处理

1.将顺序流转换为并行流(生成1 - n,转为并行流)
在这里插入图片描述
并行归纳操作
在这里插入图片描述
如果想将并行流转为顺序流,可以使用sequential方法。流水线会并行执行,因为最后调用的是它。
在这里插入图片描述
最后一次parallel或sequential调用会影响整个流水线。

并行流内部使用了默认的ForkJoinPool,它默认的线程数量就是你的处理器数量。可以通过java.util.concurrent.ForkJoinPool.common. parallelism来改变线程大小

共享可变状态会影响并行流以及并行计算,下面的代码每次执行结果都不一样。
在这里插入图片描述
在这里插入图片描述
高效的使用并行流:1.留意装箱,装箱拆箱会大大降低性能,可以使用原始类型流IntStream等。2.有些操作在并行流上性能就很差。limit、findFirst等依赖元素的顺序性。findAny比findFirst性能高,因为不用按顺序执行。可以调用unordered方法把有序流变为无序流。3.
考虑背后的数据结构是否易于分解。ArrayList比LinkedList易于分解。4.考虑终端合并步骤的代价大小。
在这里插入图片描述

分支合并框架Fork/JOIN

分支/合并框架的目的是以递归方式将可以并行的任务拆分成更小的任务,然后将每个子任务的结果合并起来生成整体结果。它是ExecutorService接口的一个实现,它把子任务分配给线程池(称为ForkJoinPool)中的工作线程。

RecursiveTask任务
要把任务提交到这个池,必须创建RecursiveTask的一个子类,其中R是并行化任务(以 及所有子任务)产生的结果类型,或者如果任务不返回结果,则是RecursiveAction类型。需要实现protected abstract R compute();方法,该方法需要同时定义了将任务拆分成子任务的逻辑,以及无法再拆分或不方便再拆分时,生成单个子任务结果的逻辑。
在这里插入图片描述
分支/合并过程
在这里插入图片描述
代码示例
在这里插入图片描述
使用多个ForkJoinPool实例是没什么意义的,一般来说实例一次,把实例保存在静态字段中。
在这里插入图片描述
对一个任务调用join方法会阻塞调用方,直到该任务做出结果。因此,有必要在两个子任务的计算都开始之后再调用它。否则,每个子任务都必须等待另一个子任务完成才能启动。
不应该在RecursiveTask内部使用ForkJoinPool的invoke方法。相反,你应该始终直接调用compute或fork方法,只有顺序代码才应该用invoke来启动并行计算。
对子任务调用fork方法可以把它排进ForkJoinPool。同时对左右两边的子任务调用它似乎很自然,但这样做效率要比直接对其中一个调用compute低。这样做你可以为将其中一个子任务重用同一线程,从而避免在线程池中多分配一个任务造成的开销。
分支/合并框架需要“预热 ”或者说要执行几遍才会被JIT编译器优化。编译器内置的优化可能会为顺序版本带来一些优 (例如执行死码分析,去掉从未被使用的计算)。

分支/合并框架工程用一种称为工作 取(work stealing)的技术来解决这个问题。在实际应 用中,这意味着这些任务差不多被平均分配到ForkJoinPool中的所有线程上。每个线程都为分 配给它的任务保存一个双向链式队列,每完成一个任务,就会从队列头上取出下一个任务开始执行。当某个线程完成自己队列上的任务时,会从其他双向队列的尾部取出任务帮忙执行。
在这里插入图片描述
Spliterator自动拆分流
Spliterator接口,和Iterator一样,Spliterator也用于遍历数据源中的元素
在这里插入图片描述
T是Spliterator遍历元素的类型,tryAdvance方法的行为类似普通的 Iterator,因为它会按顺序一个一个使用Spliterator中的元素,并且如果还有其他元素要遍历就返回true。但trySplit是专为Spliterator接口设计的,因为它可以把一些元素划出去分给第二个Spliterator(由该方法返回),让他们两个并行处理。Spliterator还可通过 estimateSize方法估计还 下多少元素要遍历,因为即使不那么确 ,能快速算出来是一个值 也有助于让拆分均匀一点。

拆分过程
将Stream 分成多个部分的算法是一个递归过程。第一步是对第一个 Spliterator调用trySplit,生成第二个Spliterator。第二步对这两个Spliterator调用 trysplit,这样总共就有了四个Spliterator。这个框架不断对Spliterator调用trySplit 直到它返回null,表明它处理的数据结构不能再分。最后,这个递归拆分过程到第四步就终止了,这时所有的Spliterator在调用trySplit时都返回了null。
在这里插入图片描述
Spliterator接口声明的最后一个抽象方法是characteristics,它将返回一个int,代表Spliterator本身特性集的编码。
在这里插入图片描述
内部迭代可以并行处理一个流,当流无法正确并行时,需要去实现一个Spliterator。代码中不用显示使用线程。
并行流,需要我们使用正确合理的数据结构。
fork/join框架是递归的将任务拆分,并将结果汇总。
Spliterator定义了并行流如何拆分它要遍历的数据。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值