2015-11-21 58 views
10

我已經獲得了用於同步推送/彈出元素的ConcurrentLinkedDeque, 和我有一些異步任務從堆棧中獲取一個元素,如果此操作元素有鄰居它推動它堆疊。如何檢查在ExecutorService上運行的所有任務是否完成

示例代碼:

private ConcurrentLinkedDeque<Item> stack = new ConcurrentLinkedDeque<>(); 
private ExecutorService exec = Executors.newFixedThreadPool(5); 

    while ((item = stack.pollFirst()) != null) { 
       if (item == null) { 
       } else { 
        Runnable worker = new Solider(this, item); 
        exec.execute(worker); 
       } 
      } 

    class Solider{ 
     public void run(){ 
      if(item.hasNeighbors){ 
       for(Item item:item.neighbors){ 
        stack.push(item) 
       } 
      } 
     } 
    } 

我想有while循環,回答了問題補充發言 - 「在遺囑執行人有關的任務是工作?」

回答

24

如果您使用ExecutorService.execute(Runnable),沒有一種乾淨的方式來檢查是否所有的Runnable都已完成。除非你在Runnable本身中構建了一個機制(這在我看來是sl)不馴的)。

相反:
使用ExecutorService.submit(Runnable)。此方法將返回一個Future<?>,它是可運行結果的句柄。使用期貨提供了一種乾淨的方式來檢查結果。

所有你需要做的就是保持您提交的Future列表,然後你就可以在期貨,要麼整個列表的迭代:
    A)等待所有的期貨阻塞做方式或
    B)檢查是否所有的期貨都以非阻塞的方式完成。

這裏是一個代碼示例:

List<Future<?>> futures = new ArrayList<Future<?>>(); 
ExecutorService exec = Executors.newFixedThreadPool(5); 

// Instead of using exec.execute() use exec.submit() 
// because it returns a monitorable future 
while((item = stack.pollFirst()) != null){ 
    Runnable worker = new Solider(this, item); 
    Future<?> f = exec.submit(worker); 
    futures.add(f); 
} 

// A) Await all runnables to be done (blocking) 
for(Future<?> future : futures) 
    future.get(); // get will block until the future is done 

// B) Check if all runnables are done (non-blocking) 
boolean allDone = true; 
for(Future<?> future : futures){ 
    allDone &= future.isDone(); // check if future is done 
} 
+0

我想已經有一個在Java方法用於此:< 反正!我用過你的解決方案,效果很好,謝謝! :) – user4129715

+0

在這裏,allDone的目的是什麼,不能預測future.isDone會自己返回真或假?順便說一句 - 偉大的答案! – User3

+1

@ User3'allDone'的目的是得到一個單一的布爾值,指示期貨的_all_是否完成(通過使用&&操作符)。 'future.isDone()'只能用於檢查單個Future是否完整 –

相關問題