[英]Any reason why CachedThreadPool would be at full capacity but not initiate a second thread?
想象一下,需要時間的軟件會收集大量文本文件(每個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
,另一個運行while循環中的其余部分,最多到fut.get()
。
關於幕后可能發生什么的任何想法? 代碼“太順序”是否可以使用線程池?
你正在以錯誤的方式使用期貨來並行執行。 您需要先提交所有任務並保存他們的未來,然后再打電話。 調用get等待任務完成。
你現在正在做的是提交一個在自己的線程上執行的任務,然后主線程等待任務完成。 沖洗並重復。
你說你期待兩個線程。 這確實是你擁有的 - 主線程和一個執行程序線程。
問題不在於線程池實現。 您嘗試一次獲得一個Future
,因此您的程序基本上是單線程的。
你應該做的是創建你的Callable
的Collection
並使用:
final List<Future<Set<Fragment>>> results
= executor.invokeAll(yourCollectionOfCallables);
然后循環results
。 當一個任務完成時,線程池將盡力啟動具有新任務的線程; 更重要的是,當您遍歷所有列表時,保證所有任務都已完成(成功與否)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.