看了流的并行方法,你可能想知道并行流使用的线程从哪里来,有多少个,以及如何自定义流程。并行流内部使用默认值ForkJoinPool
,默认情况下,它具有与处理器一样多的线程,如由Runtime.getRuntime().availableProcessors()
。但是您可以使用系统属性更改此池的大小java.util.concurrent.ForkJoinPool.common.parallelism
.
并行流在后台用于并行执行操作的基础设施是 Java 7 中引入的 fork/join 框架。为了正确使用它们,充分了解并行流的内部结构至关重要。 fork/join 框架旨在将可并行任务递归地拆分为更小的任务,然后组合每个子任务的结果以生成总体结果。这是一个实现ExecutorService
接口,它分发这些
线程池中工作线程的子任务,称为ForkJoinPool
.
The Spliterator
代表“可分割迭代器”。与迭代器一样,拆分器用于遍历源的元素,但它们也被设计为并行执行此操作。尽管您在实践中可能不必开发自己的 Spliterator,但了解如何开发将使您对并行流的工作原理有更广泛的了解。
将 Stream 拆分为多个部分的算法是一个递归过程。第一步,调用一个方法trySplit
在第一个 Spliterator 上调用并生成第二个 Spliterator。然后在步骤 2 中再次调用这两个 Spliterator,总共有 4 个。框架不断调用 Spliterator 上的 trySplit 方法,直到它返回 null 以指示数据
它正在处理的结构不再可分。最后,当所有 Spliterator 都向 trySplit 调用返回 null 时,此递归拆分过程终止。
Spliterator 接口声明的最后一个抽象方法是 features,它返回一个 int 编码 Spliterator 本身的特征集。 Spliterator 客户端可以使用这些特性来更好地控制和优化其使用。他们是:ORDERED
, DISTINCT
, SORTED
,
SIZED
, NONNULL
, IMMUTABLE
, CONCURRENT
, and SUBSIZED
。根据流的具体特征,它实际上可能根本不并行运行。
详细解释这一切的书是:Java 8 实战:Lambda、流和函数式编程
(拉乌尔-加布里埃尔·乌尔玛、马里奥·福斯科和艾伦·麦克罗夫特) https://rads.stackoverflow.com/amzn/click/com/1617291994,来自曼宁。参见第 7 章:并行数据处理和性能.