在Java 8中并行生成了多少个线程?

Sin*_*nky 59 java multithreading java.util.concurrent java-8

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

list.parallelStream().forEach(/** Do Something */);
Run Code Online (Sandbox Code Playgroud)

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

另外,每个线程都可以获得相同数量的项目,还是随机分配?

Umb*_*ndi 63

Oracle的并行流实现[1]使用当前线程,除此之外,如果需要,还使用组成默认fork连接池的线程,ForkJoinPool.commonPool()默认大小等于比CPU核心数小1的默认大小. .

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

-Djava.util.concurrent.ForkJoinPool.common.parallelism=8
Run Code Online (Sandbox Code Playgroud)

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

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

关于订单,只要线程可用,就会立即执行作业,而不是特定的顺序.

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

  • 应该注意的是,`Stream` API使用`ForkJoinPool`是一个实现细节.因此,这两种解决方案都适用于Oracle当前的实现,但不能保证在任何地方都能正常工作. (11认同)
  • 看起来这里的重载是有意义的——“parallelStream(int maxDegreeOfParallelism)”——你知道,就像我们在 C# 中一样。 (6认同)
  • 也许值得补充的是,如果任务数量足够小,并行流可能实际上在主线程中运行. (3认同)

edh*_*ned 5

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

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