2011-06-09 75 views
5

我有一個類,它產生了一堆線程,必須等到所有衍生線程完成。 (我需要計算所有線程完成的時間)。Java:Multithreading -Wait/notifyAll問題

MainClass產生所有的線程,然後檢查是否所有線程都完成,然後它可以調用自己完成。

此邏輯是否有效。如果是這樣,是否有更好的方法來做到這一點?如果不是,我想更好地理解這種情況。

class MainClass{ 
    private boolean isCompleted; 
    ... 
    for(task : tasks){ 
     threadpool.execute(task); 
    } 

    for(task : tasks){ 
     if(!task.isCompleted()){ 
      task.wait() 
     } 
    } 

    isCompleted = true; 
} 


class Task{ 
    public void run(){ 
     .... 
     .... 
     synchronized(this){ 
      task.completed = true; 
      notifyAll(); 
     } 
    } 
} 
+1

我認爲你的代碼不起作用,因爲你忘記了'wait()'附近的'synchronized'塊。查看我的答案以獲得更好(更快)的解決方案。 – 2011-06-09 17:30:06

+0

太棒了!正是我在找什麼。我需要至少5分鐘。在我可以關閉它之前。 :) – 2011-06-09 17:31:32

回答

11

notifyAll()是比較慢。更好的方法是使用CountDownLatch

import java.util.concurrent.CountDownLatch; 

int n = 10; 
CountDownLatch doneSignal = new CountDownLatch(n); 
// ... start threads ... 
doneSignal.await(); 

// and within each thread: 
doWork(); 
doneSignal.countDown(); 
+1

+1,但你沒有解釋爲什麼'CountDownLatch'會是一個更好的選擇,除了任意(並且隱含地)說它比等待通知方案更快。 – mre 2011-06-09 17:30:13

+1

我確實有一個問題。如果倒計數從未達到0.線程是否掛起? – 2011-06-09 17:39:19

+0

@Vanchinathan Chandrasekaran是的。 – 2011-06-09 17:47:50

4

有沒有必要等待/通知在這種情況下。您可以循環訪問線索並致電join()。如果線程已經完成,MainClass線程將等待下一個線程。

您可能也想看看java.util.concurrent包中的更高級別的實用程序。

+0

+1,用於提及簡單的解決方案(即'Thread.join()')和引用'java.util.concurrent'包作爲更好的選擇。 – mre 2011-06-09 17:34:12

4

所有這些都可以通過java.util.concurrent.ExecutorService完成。

class MainClass { 
    ... 
    ExecutorService executor = Executors.newCachedThreadPool(); 
    List<Callable> tasks = ...; // prepare your tasks 

    // this invokes all tasks in parallel and waits until all are done 
    executor.invokeAll(tasks); 
    ... 
} 

就是這樣。

+0

我剛剛嘗試過,程序在'invokeAll'後運行了一陣子。我發現你必須調用'executor.shutdown();'釋放所有的線程和程序可以立即結束。 – 2013-12-07 22:08:03