看流的parallel方法,你可能想知道parallel流使用的线程是从哪里来的,有多少,如何自定义进程。并行流在内部使用默认的ForkJoinPool,默认情况下,它的线程数与处理器数一样多,由Runtime.getRuntime().availableProcessors() 返回。但是您可以使用系统属性java.util.concurrent.ForkJoinPool.common.parallelism 更改此池的大小。
并行流在幕后用于并行执行操作的基础设施是 Java 7 中引入的 fork/join 框架。为了正确使用并行流内部结构,了解并行流内部结构至关重要。 fork/join 框架旨在递归地将可并行化的任务拆分为更小的任务,然后组合每个子任务的结果以产生整体结果。它是ExecutorService 接口的一个实现,它分发那些
线程池中工作线程的子任务,称为ForkJoinPool。
Spliterator 代表“可拆分迭代器”。与迭代器一样,拆分器用于遍历源的元素,但它们也被设计为并行执行此操作。尽管您可能不必在实践中开发自己的 Spliterator,但了解如何这样做将使您对并行流的工作方式有更广泛的了解。
将 Stream 拆分为多个部分的算法是一个递归过程。在第一步中,在第一个 Spliterator 上调用一个名为 trySplit 的方法并生成第二个 Spliterator。然后在第 2 步中再次调用这两个 Spliterator,总共有四个。框架不断在 Spliterator 上调用 trySplit 方法,直到它返回 null 以表示数据
它正在处理的结构不再是可分的。最后,当所有 Spliterator 都将 null 返回给 trySplit 调用时,此递归拆分过程终止。
Spliterator 接口声明的最后一个抽象方法是characteristics,它返回一个int 编码Spliterator 本身的特征集。 Spliterator 客户端可以使用这些特性来更好地控制和优化其使用。它们是:ORDERED、DISTINCT、SORTED、
SIZED、NONNULL、IMMUTABLE、CONCURRENT 和 SUBSIZED。根据流的具体特性,它实际上可能根本不会并行运行。
详细解释这一切的书是:Java 8 in Action: Lambdas, streams, and functional-style programming
(Raoul-Gabriel Urma, Mario Fusco, and Alan Mycroft),来自曼宁。参见第 7 章:
并行数据处理和性能。