Java8的Collection.parallelStream如何工作?

ovu*_*tin 3 java parallel-processing multithreading java-8 java-stream

CollectionJava SDK 8 中的类附带了一个新方法“ parallelStream”。

显然,这种新方法提供了一种并行消费集合的机制。

但是,我想知道Java是如何实现这种并行性的。其根本机制是什么?它只是多线程执行吗?或者 fork/join 框架(随 Java SDK 7 一起提供)会介入吗?如果答案都不是,那么它是如何工作的以及它相对于其他两种机制的优势是什么?

Mar*_*rcG 5

看看stream\xe2\x80\x99s并行方法,你可能想知道并行流使用的线程从哪里来,有多少个,以及如何自定义进程。并行流在内部使用 default ForkJoinPool,默认情况下,它具有与处理器一样多的线程,如由Runtime.getRuntime().availableProcessors()。但您可以使用系统属性更改此池的大小java.util.concurrent.ForkJoinPool.common.parallelism

\n\n

并行流在后台用于并行执行操作的基础设施是 Java 7 中引入的 fork/join 框架。为了正确使用并行流,充分了解并行流的内部结构至关重要。fork/join 框架旨在将可并行的任务递归地拆分为更小的任务,然后组合每个子任务的结果以产生总体结果。它\xe2\x80\x99是该接口的实现ExecutorService,它将这些子任务分配给线程池中的工作线程,称为ForkJoinPool

\n\n

Spliterator\xe2\x80\x9c 可分割迭代器。\xe2\x80\x9d 与迭代器一样,Spliterator 用于遍历源的元素,但它们\xe2\x80\x99 也被设计为并行执行此操作。尽管您在实践中可能不必开发自己的 Spliterator,但了解如何开发将使您对并行流的工作原理有更广泛的了解。

\n\n

将 Stream 拆分为多个部分的算法是一个递归过程。第一步,调用一个方法trySplit在第一个 Spliterator 上调用一个名为 的方法并生成第二个 Spliterator。然后在步骤 2 中,它\xe2\x80\x99 再次调用这两个 Spliterator,总共有 4 个。框架不断调用 Spliterator 上的 trySplit 方法,直到返回 null 为止,以表明它处理的数据结构不再可整除。最后,当所有 Spliterator 都向 trySplit 调用返回 null 时,此递归拆分过程终止。

\n\n

Spliterator 接口声明的最后一个抽象方法是 features,它返回一个 int 编码 Spliterator 本身的特征集。Spliterator 客户端可以使用这些特性来更好地控制和优化其使用。它们是:ORDERED, DISTINCT, SORTED,\n SIZED, NONNULL, IMMUTABLE, CONCURRENT, 和SUBSIZED。根据流的具体特征,它实际上可能根本不并行运行。

\n\n

详细解释这一切的书是:《Java 8 in Action:Lambdas、streams 和函数式编程》(Raoul-Gabriel Urma、Mario Fusco 和 Alan Mycroft),来自 Manning。请参阅第 7 章:\n并行数据处理和性能

\n