gpt4 book ai didi

java - ForkJoinPool 似乎浪费了一个线程

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:14:41 28 4
gpt4 key购买 nike

我正在比较测试程序的两个变体。两者都使用 4 线程运行 ForkJoinPool在具有四个内核的机器上。

在“模式 1”中,我使用池非常像执行程序服务。我将一堆任务扔到 ExecutorService.invokeAll 中。与普通的固定线程执行器服务相比,我获得了更好的性能(即使有对 Lucene 的调用,在其中执行一些 I/O)。

这里没有分而治之。说真的,我愿意

ExecutorService es = new ForkJoinPool(4);
es.invokeAll(collection_of_Callables);

在“模式 2”中,我将单个任务提交到任务池,并在该任务中调用 ForkJoinTask.invokeAll 来提交子任务。因此,我有一个继承自 RecursiveAction 的对象,并将其提交到池中。在该类的计算方法中,我对来自 不同 类的对象集合调用 invokeAll,该类也继承自 RecursiveAction。出于测试目的,我一次只提交一个第一个对象。我天真地希望看到所有四个线程都在忙什么,因为调用 invokeAll 的线程会为自己获取其中一个子任务,而不是坐下来阻塞。我能想到它可能无法那样工作的一些原因。

在 VisualVM 中观察,在模式 2 中,一个线程几乎总是在等待。我希望看到的是调用 invokeAll 的线程立即开始处理其中一个调用的任务,而不是只是坐着不动。这肯定比使用普通线程池尝试此方案所导致的死锁要好,但是,怎么办?它是否会保留一个线程以防提交其他内容?而且,如果是这样,为什么模式 1 中没有同样的问题?

到目前为止,我一直在使用添加到 java 1.6 的引导类路径中的 jsr166 jar 来运行它。

最佳答案

ForkJoinTask.invokeAll 正在派生所有任务,但在列表中是第一个。它自己运行的第一个任务。然后它加入其他任务。它的线程不会以任何方式释放到池中。所以你所看到的,它是线程阻塞在其他任务上才能完成。

关于java - ForkJoinPool 似乎浪费了一个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9677506/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com