4

我在仿真系統,其中在每個時間步長,我必須模擬許多型號。我用了一個FixedThreadPool來加速計算:現在java的重用執行

ExecutorService executor = Executors.newFixedThreadPool(nThread); 
for (Model m : models) { 
    executor.execute(m.simulationTask()); 
} 
executor.shutdown(); 
while (! executor.awaitTermination(10, TimeUnit.MINUTES)) { 
    System.out.println("wait"); 
} 

,執行人不能調用shutdown()後用於​​新任務。有沒有辦法重置執行程序,所以我可以在下一個模擬步驟中重用現有的執行程序(及其線程)?

回答

7

,如果你稍微調整你的代碼,你可以重用執行服務。

Collection<Callable<Integer>> tasks = new ArrayList<Callable<Integer>>(16); 
for (Model m : models) { 
    tasks.add(m.simulationTask()); 
} 

ExecutorService executor = Executors.newFixedThreadPool(nThread); 
try { 
    executor.invokeAll(tasks); 
} catch(InterruptedException ie) { 
    // Handle this 
} 

基本上,你收集所有的任務,執行它們,並等待執行,然後再繼續。當然,您也可以在每個時間步驟中使用新的Executor服務,但至少您有選擇。

注意事項:我沒有編譯代碼,所以有可能是錯誤的。爲了方便,我還假設了一個Integer參數類型。

+1

在進入下一步之前,您尚未展示如何等待所有任務完成。 – dogbane 2012-01-27 17:10:33

+1

@dogbane - 'invokeAll'等待所有任務完成。 – Perception 2012-01-27 17:12:44

+0

,因爲他正在使用'execute(Runnable)',它沒有返回值,我們可以去'Callable '也許? – mzzzzb 2012-10-20 05:08:26

1

您可以編寫自己的實現Executor接口。除此之外,我知道的大部分默認實現都是在shutdown()之後獲得線程和內存清理,所以沒有(據我所知)預先制定的解決方案。

考慮到shutdown()很可能做了很多清理和垃圾收集的,它不完全清楚爲什麼重新開始會比accquiring新Executor更好,也許你應該看看教程about extending ThreadPoolExecutor with a pause/resume set of methods,而不是添加到這不同於能力關掉。

0

剛剛收購另一ExecutorService。無論如何,開銷很小。

如果你堅持重複使用相同的執行者,你可以實現自己的屏障機制。在提交新任務後,自動遞增計數器。當任務完成時,以原子方式遞減計數器。在主線程中等待,直到計數器爲零。喜歡的東西:

// globally visible objects 
AtomicInteger counter = new AtomicInteger(0); 
Object signal = new Object(); 

ExecutorService executor = Executors.newFixedThreadPool(nThread); 
for (Model m : models) { 
    counter.getAndIncrement(); 
    executor.execute(m.simulationTask()); 
} 

synchronized(signal) { 
    while(count.get() > 0) { 
     signal.wait(); 
    } 
} 

然後你的任務run內:

public void run() { 
    // original code 
    // at the end: 
    synchronized(signal) { 
     counter.getAndDecrement(); 
     signal.notify(); 
    }   
} 
+0

我不會說,通過創建線程池的支持一個Executor具有最小的開銷...... – 2012-01-27 16:12:06

+0

這要看他有多少線程使用。如果這個數字很小,那麼沒有太多的開銷。另外,如果他正在執行的任務是粗粒度的,則對於其他應用程序來說它是微不足道的。 – Tudor 2012-01-27 16:14:40

1

聲明你ExecutorService作爲成員到您的類和你想重新使用它。不要在它上面調用shutDown(),因爲它不會接受任何更多的任務。當然你的任務應該很好地結束,他們也應該在某個時候終止。