在 JDK8中,当我使用并行流时,会产生多少个线程? 例如,在代码中:
list.parallelStream().forEach(/** Do Something */);
如果这个列表有100000个项目,会产生多少个线程?
另外,每个线程是否获得相同数量的要处理的项,还是随机分配的?
Oracle 的并行流实现[1]使用当前线程,除此之外,如果需要,还使用组成默认 fork 连接池 ForkJoinPool.commonPool()的线程,它的默认大小等于 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 甚至不能使用 ForkJoinPool在内部根据 ForkJoinTask.fork的行为完全无用的渲染备选方案(详情请参阅 看这里)。
ForkJoinPool
ForkJoinTask.fork
虽然@uraimo 是正确的,但答案取决于“ Do Something”具体做了什么。Stream API 使用 CountedCompleter 类,该类有一些有趣的问题。由于 F/J 框架不使用单独的对象来保存结果,长链可能导致 OOME。此外,这些长链有时会导致堆栈溢出。正如我在 这篇文章。中指出的那样,这些问题的答案是使用 Paraquential 技术
The other problem is excessive thread creation when using nested parallel forEach.