在 Java 8 中的 parallelStream 中生成了多少个线程?

在JDK8中,当我使用parallelStream时会生成多少个线程?例如,在代码中:

list.parallelStream().forEach(/** Do Something */);

如果此列表有 100000 个项目,将生成多少个线程?

此外,每个线程是否获得相同数量的项目来处理,还是随机分配?


答案 1

Oracle的并行流实现[1]使用当前线程,此外,如果需要,还可以使用组成默认分叉连接池的线程,其默认大小等于CPU内核数的一个。ForkJoinPool.commonPool()

可以使用以下属性更改公用池的默认大小:

-Djava.util.concurrent.ForkJoinPool.common.parallelism=8

或者,您可以使用自己的池:

ForkJoinPool myPool = new ForkJoinPool(8);
myPool.submit(() ->
    list.parallelStream().forEach(/* Do Something */);
).get();

关于顺序,一旦线程可用,作业将立即执行,没有特定的顺序。

正如@Holger正确地指出的那样,这是一个特定于实现的细节(文档底部只有一个模糊的引用),这两种方法都可以在Oracle的JVM上工作,但绝对不能保证在其他供应商的JVM上运行,该属性不能存在于非Oracle实现中,Streams甚至不能使用基于完全无用的行为的内部渲染替代方案(有关详细信息,请参阅此处)。ForkJoinPoolForkJoinTask.fork


答案 2

虽然@uraimo是正确的,但答案完全取决于“做某事”到底做了什么。parallel.streams API 使用 CountedCompleter 类,该类存在一些有趣的问题。由于 F/J 框架不使用单独的对象来保存结果,因此长链可能会导致 OOME。此外,这些长链有时会导致堆栈溢出。这些问题的答案是使用我在本文中指出的Paraquential技术

另一个问题是在使用嵌套并行 forEach 时创建过多的线程。