2011-03-28 71 views
2

我有一個線程必須等待來自不同線程的多個對象。如何等待幾個對象

@Override 
public void run() { 
    while (true) { 
     for (BackgroundTask task : tasks) { 
      synchronized (task) { 
       if (task.isReady()) { 
        task.doTask(); 
       } 
      } 
     } 
    } 
} 

但它是一個愚蠢的使用CPU時間。 如何等待幾個對象?

回答

1

請使用notifyaAll()而不是notify(),因爲notify會喚醒單線程,其中notifyAll()會喚醒所有正在等待的線程。

+0

據我所知,notifyAll()只喚醒所有等待線程中的一個對象。我需要在一個線程中等待幾個對象。 – itun 2011-03-28 14:16:07

+0

@itun線程的等待是完全串行的。也就是說,在任何給定的時間只有一個線程可以等待一個對象(監視器)。這違反了您正在查找的功能類型,並且不可用。 – 2011-03-28 14:18:40

+0

等待並通知有幾個警告(例如線程在通知未被調用時被喚醒)。您應該使用更高級別的組件,例如BlockingQueue或CountDownLatch。 – 2011-03-28 14:28:13

0

您可以在Object上使用notify()wait()。你如何使用它取決於你的程序的結構。

+0

這將是很好的在這裏指出,當一個對象在另一個等待,等待的對象可能會被喚醒,而無需通知已經永遠被調用。也就是說,必須始終在檢查條件的循環中調用wait。 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4308396 – 2011-03-28 14:32:42

1

如果您可以修改BackgroundTask類,請在準備就緒時通知跑步者。爲你的runner類添加一個隊列,每當一個任務就緒時,它就可以將它自己添加到隊列中並通知它。

然後,runner類在隊列爲空時等待隊列,並在隊列沒有時從隊列中取出物品運行。

+0

謝謝你,這是個好主意! – itun 2011-03-28 14:16:54

3

IMO CountDownLatch將是一個好方法。從的Javadoc引用:

class Driver2 { // ... 
    void main() throws InterruptedException { 
    CountDownLatch doneSignal = new CountDownLatch(N); 
    Executor e = ... 

    for (int i = 0; i < N; ++i) // create and start threads 
     e.execute(new WorkerRunnable(doneSignal, i)); 

    doneSignal.await();   // wait for all to finish 
    } 
} 

class WorkerRunnable implements Runnable { 
    private final CountDownLatch doneSignal; 
    private final int i; 
    WorkerRunnable(CountDownLatch doneSignal, int i) { 
     this.doneSignal = doneSignal; 
     this.i = i; 
    } 
    public void run() { 
     try { 
     doWork(i); 
     doneSignal.countDown(); 
     } catch (InterruptedException ex) {} // return; 
    } 

    void doWork() { ... } 
} 
+0

我認爲BlockingQueue對我來說更方便。因爲你的建議適合於幾個線程的任務,並且我需要一個長線程來執行幾個任務。 – itun 2011-03-28 14:52:18

+0

@itun:你說「等待來自不同線程的多個對象」,這就是爲什麼我假定你有多個線程在運行,處理驅動程序線程需要等待的東西。您可以輕鬆調整爲您的方案發布的代碼,並且應該完美地工作。 :-) – 2011-03-28 15:29:13

+0

我不知道該怎麼做。當所有對象準備就緒時,doneSignal會等待,但是我需要該驅動程序等待,直到至少有一個對象不準備好爲止 – itun 2011-03-28 19:29:35