ForkJoinPool大小动态增加?

相关:ParallelStream 上的 CompletableFuture 被批处理并且运行速度比顺序流慢?

我正在研究通过 parallelStream 和 CompletableFutures 并行化网络调用的不同方法。因此,我遇到过这种情况,Java 的 parallelStream 使用的 ForkJoinPool.commonPool() 的大小动态增长,从 ~ #Cores 到最大值 64。

爪哇细节:
$ java -version

openjdk version "11.0.10" 2021-01-19
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.10+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.10+9, mixed mode)

显示这种行为的代码如下(完整的可执行代码在这里)

openjdk version "11.0.10" 2021-01-19
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.10+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.10+9, mixed mode)

示例输出:

16:07:17.443 [pool-2-thread-7] INFO  generalworks.parallelism.DummyProcess -  44 going to sleep. poolsize: 11
16:07:17.443 [pool-2-thread-9] INFO  generalworks.parallelism.DummyProcess -  7 going to sleep. poolsize: 12
16:07:17.443 [pool-2-thread-4] INFO  generalworks.parallelism.DummyProcess -  6 going to sleep. poolsize: 12
16:07:17.444 [pool-2-thread-13] INFO  generalworks.parallelism.DummyProcess -  82 going to sleep. poolsize: 13
16:07:17.444 [pool-2-thread-14] INFO  generalworks.parallelism.DummyProcess -  26 going to sleep. poolsize: 14
16:07:17.444 [pool-2-thread-15] INFO  generalworks.parallelism.DummyProcess -  96 going to sleep. poolsize: 15
16:07:17.445 [pool-2-thread-16] INFO  generalworks.parallelism.DummyProcess -  78 going to sleep. poolsize: 16
.
.
16:07:18.460 [pool-2-thread-79] INFO  generalworks.parallelism.DummyProcess -  2 going to sleep. poolsize: 64
16:07:18.460 [pool-2-thread-71] INFO  generalworks.parallelism.DummyProcess -  36 going to sleep. poolsize: 64
16:07:18.460 [pool-2-thread-74] INFO  generalworks.parallelism.DummyProcess -  77 going to sleep. poolsize: 64
16:07:18.461 [pool-2-thread-83] INFO  generalworks.parallelism.DummyProcess -  86 going to sleep. poolsize: 64

我知道公共池中的线程数,即它parallelism基于可用内核的最大数量,所以由于我的笔记本电脑有 12 个内核,我开始时的并行度为 11。但我不明白为什么它以一种方法不断攀升,但在另一种方法中,它的大小保持不变

回答

我相信你的答案在这里(ForkJoinPool实现):

                        if ((wt = q.owner) != null &&
                            ((ts = wt.getState()) == Thread.State.BLOCKED ||
                             ts == Thread.State.WAITING))
                            ++bc;            // worker is blocking

在您的代码的一个版本中,您阻塞 on Thread.sleep,将线程置于TIMED_WAITING状态,而在另一个版本中,您阻塞 on CompletableFuture.join(),将其置于WAITING状态。该实现区分了这些并展示了您观察到的不同行为。

里面还有特殊情况的代码CompletableFuture,让它与 配合ForkJoinPool,以防止在等待结果时出现饥饿:

            if (Thread.currentThread() instanceof ForkJoinWorkerThread)
                ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q);

与您首先进行测试的原因相关的结论:Thread.sleep()没有正确模拟长时间的网络呼叫。如果您进行了实际操作或其他一些阻塞操作,它将通过扩展池来进行补偿。


以上是ForkJoinPool大小动态增加?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>