gpt4 book ai didi

java - 为什么 CachedThreadPool 会满负荷但不启动第二个线程,有什么原因吗?

转载 作者:行者123 更新时间:2023-12-02 06:10:46 24 4
gpt4 key购买 nike

想象一个需要时间的软件,它接收一堆文本文件(每个 100+ MB),处理它们并放入数据库。我试图通过利用更多核心(这台机器恰好是 8 个,带有超线程的四核 i7)来对其进行一些优化。

考虑以下代码:

    ExecutorService es = Executors.newCachedThreadPool(
new ThreadFactory() {
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix = "awesome-thread-";

public Thread newThread(Runnable r) {
Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());
if (t.isDaemon())
t.setDaemon(false);
return t;
}
});

while((e = upp.getNextEntry()) != null){

// start time-consuming process in a separate thread to speed up
Future<Set<Fragment>> fut = es.submit(new FragmentTask(e.getSomeProperty()));

/* do other stuff #sequentially# with entry e
* it may or may not take as long as previous step
* depending on e
*/

Set<Fragment> set = fut.get();
for(Fragment frag : set){
// do stuff with frag
}
}

此处,FragmentTask 包含一个递归算法,执行时间从几毫秒到几千毫秒不等,具体取决于 e

我最初将线程池实现为 FixedThreadPool,但是当我目视检查线程的运行情况(通过 JVisualVM)时,我意识到线程通常处于空闲状态。我想我会尝试使用 CachedThreadPool 作为替代方案,但看起来该池是一个单个线程,在整个 while 循环中几乎以 100% 的速度运行。在此过程中的任何时候都不会创建池的辅助线程,并且其他核心也几乎处于空闲状态。真正有趣的是,执行 while 循环中其余部分的“主”工作线程几乎一直在“等待”。

我觉得这有点奇怪,因为我预计至少有两个线程应该能够以更高的效率运行,一个运行 FragmentTask ,另一个运行其余的内容循环,直到 fut.get()

对于幕后可能发生的事情有什么想法吗?对于要使用的线程池来说,代码是否“过于连续”?

最佳答案

问题不在于线程池实现。您尝试一次获取一个 Future,因此您的程序本质上是单线程的。

您应该做的是创建 CallableCollection 并使用:

final List<Future<Set<Fragment>>> results
= executor.invokeAll(yourCollectionOfCallables);

然后循环您的结果。当一个任务完成时,线程池会尽力启动新任务的线程;更重要的是,当您迭代所有列表时,可以保证所有任务都已完成(成功或失败)。

关于java - 为什么 CachedThreadPool 会满负荷但不启动第二个线程,有什么原因吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21911624/

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