我可以重现您看到的行为,其中并行性与您指定的fork-join池并行性的并行性不匹配。将fork-
join池的并行度设置为10,并将集合中的元素数增加到50后,我看到基于列表的流的并行度仅上升到6,而基于集合的流的并行度从未超过2。
但是请注意,这种将任务提交给fork-join池以在该池中运行并行流的技术是一种“技巧”,并且 不能保证 能正常工作。实际上, 未指定
用于执行并行流的线程或线程池。默认情况下,使用公共的fork-join池,但是在不同的环境中,最终可能会使用不同的线程池。(请考虑应用程序服务器内的容器。)
在java.util.stream.AbstractTask类中,该
LEAF_TARGET字段确定完成的拆分数量,而拆分又确定了可以实现的并行数量。该字段的值基于
ForkJoinPool.getCommonPoolParallelism()哪个当然使用了公共池的并行性,而不取决于运行任务的任何池。
可以说这是一个错误(请参阅OpenJDK问题JDK-8190974),但是,整个区域都未指定。但是,系统的这一领域肯定需要发展,例如在拆分策略,可用并行性,处理阻塞任务等方面。JDK的未来版本可能会解决其中一些问题。
同时,可以通过使用系统属性来控制公共fork-join池的并行性。如果将此行添加到程序中,
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "10");并且您在公共池中运行流(或者,如果将它们提交到具有足够高的并行性集的自己的池中),您会发现有更多的任务并行运行。
您也可以使用
-D选项在命令行上设置此属性。
同样,这不是保证的行为,将来可能会改变。但是在可预见的将来,该技术可能会对JDK 8实现有效。
更新2019-06-12:
JDK-8190974错误已在JDK
10中修复,并且该修复已向后移植到即将发布的JDK 8u版本(8u222)中。



