Java 8 的 parallelStream 中产生了多少线程?
Posted
技术标签:
【中文标题】Java 8 的 parallelStream 中产生了多少线程?【英文标题】:How many threads are spawned in parallelStream in Java 8? 【发布时间】:2015-08-28 10:16:09 【问题描述】:在JDK8 中,当我使用parallelStream 时产生了多少个线程?比如在代码中:
list.parallelStream().forEach(/** Do Something */);
如果这个列表有 100000 个项目,会产生多少个线程?
另外,每个线程是否获得相同数量的项目来处理,还是随机分配的?
【问题讨论】:
***.com/questions/21163108/… @assylias 非常好的答案。 【参考方案1】:Oracle 的并行流实现[1] 使用当前线程,除此之外,如果需要,还有构成默认 fork 连接池 ForkJoinPool.commonPool()
的线程,其默认大小等于CPU 的核心数。
可以使用此属性更改公共池的默认大小:
-Djava.util.concurrent.ForkJoinPool.common.parallelism=8
或者,您可以使用自己的池:
ForkJoinPool myPool = new ForkJoinPool(8);
myPool.submit(() ->
list.parallelStream().forEach(/* Do Something */);
).get();
关于顺序,作业将在线程可用时立即执行,没有特定顺序。
正如@Holger 正确指出的那样,这是一个特定于实现的细节(文档底部只有one vague reference),这两种方法都适用于Oracle 的JVM,但绝对不能保证适用于其他供应商的JVM,该属性不能存在于非 Oracle 实现中,Streams 甚至无法在内部使用ForkJoinPool
,从而基于ForkJoinTask.fork
的行为完全无用(see here 对此进行了详细说明)。
【讨论】:
也许值得补充的是,如果任务数量足够小,并行流实际上可能在主线程中运行。 需要注意的是,Stream
API 对ForkJoinPool
的使用是一个实现细节。因此,这两种解决方案都适用于 Oracle 当前的实现,但不能保证在任何地方都适用。【参考方案2】:
虽然@uraimo 是正确的,但答案完全取决于“做某事”的作用。 parallel.streams API 使用有一些有趣问题的 CountedCompleter 类。由于 F/J 框架不使用单独的对象来保存结果,因此长链可能会导致 OOME。此外,那些长链有时会导致堆栈溢出。正如我在this article. 中指出的那样,这些问题的答案是使用 Paraquential 技术
另一个问题是使用嵌套并行 forEach 时创建的线程过多。
【讨论】:
以上是关于Java 8 的 parallelStream 中产生了多少线程?的主要内容,如果未能解决你的问题,请参考以下文章
java 8 parallelStream() 和 sorted()
带有 spring 注释方法的 Java .parallelStream()
组合器在 java parallelStream reduce 中的实际作用是啥