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


79

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

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

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

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



@assylias真的很好。
Umberto Raimondi 2015年

Answers:


77

Oracle并行流的实现[1]使用当前线程,此外,如果需要,还使用构成默认派生连接池的线程,该线程ForkJoinPool.commonPool()的默认大小比CPU内核数小一。

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

-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甚至无法ForkJoinPool基于ForkJoinTask.fork完全无用的行为在内部使用替代项(有关详细信息,请参见此处)。


5
可能值得补充的是,如果任务数量足够少,则并行流实际上可以在主线程中运行。
assylias 2015年

15
应该注意的是,StreamAPI的使用ForkJoinPool是一个实现细节。因此,这两种解决方案都可以与Oracle当前的实现一起使用,但不能保证在任何地方都可以使用。
Holger 2015年

4

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.