2013-11-28 47 views
0

在第一個Java線程我:Java:只有在等待時才能通知線程?

while (!isDone) { 
    try { 
     synchronized (this) { 
      wait(); 
     } 
    } catch (InterruptedException e) { 
      e.printStackTrace(); 
    } 
    doSomeVeryLongRunningTask(); 
} 

在另一個線程,我想發出一個通知信號:

synchronized (thr1) { 
    thr1.notify(); 
} 

但是,如果doSomeVeryLongRunningTask()方法運行,我不想第二個線程被阻止。我只想通知第一個線程,如果它正在等待,以便第二個線程可以在不鎖定的情況下繼續執行任務。

我該如何修復上面的代碼才能實現這一目標?

回答

2

他們想解決的問題不存在。​​只有當另一個線程已經在同一個對象的​​塊同步內時塊纔會阻塞該線程。由於您的doSomeVeryLongRunningTask()將在​​塊之外被調用,因此如果另一個線程位於doSomeVeryLongRunningTask()方法內,通知線程將永遠不會被阻止。

但是這引起了另一個問題。你似乎在想,waitnotify調用總是配對。情況並非如此,您可以隨時撥打notify,無需任何人傾聽。也可能是wait調用返回「虛假」,即沒有明顯原因。因此,您需要定義另一個「硬條件」,該條件由在​​塊內修改並檢查的狀態定義。

E.g.它的情況下,你在你的thr1變量具有班級裏,你可以定義一個boolean標誌:

boolean condition; 

然後你修改你等待的方法是這樣的:

while(!isDone) { 
    try { 
    synchronized(this) { 
     while(!condition) wait(); 
     if(isDone) break;// skip doSomeVeryLongRunningTask() 
     condition=false; 
    } 
    } catch(InterruptedException e) { 
    e.printStackTrace(); 
    } 
    doSomeVeryLongRunningTask(); 
} 

而且報告代碼:

synchronized(thr1) { 
    thr1.condition=true; 
    thr1.notify(); 
} 

這樣你的通知代碼仍然不會被阻塞(至少永遠不會有很長的時間),但等待的線程將等待至少一個通知在一個循環週期內發生。

+0

「您想解決的問題不存在。」感謝您的回覆。你幫我看到了我提供的縮短問題的一個問題......'doSomeVeryLongRunningTask()'是一種同步方法。我應該刪除那裏的同步。您發佈的其他解決方案爲我提供了一些其他想法。謝謝。 – kmccoy

0

notify()調用不會阻止。只有wait()塊。即使沒有其他線程在等待,您也可以調用通知,但請確保您的算法是正確的。如果您希望僅通知一次,那麼在通知後到達的另一個線程將永遠等待()。

+0

notify()不會阻塞 - 但必須在thrd1上進行同步。有沒有更好的方法來解決這個問題? – kmccoy

1

看來是什麼阻止你的程序不是notify()(它不會阻止),而是在同一個對象上同步的兩個​​塊。

我不認爲你有什麼解決方法。檢查此鏈接以知道爲什麼:http://javarevisited.blogspot.com/2011/05/wait-notify-and-notifyall-in-java.html

+0

我基本上有一個生產者 - 消費者問題,其中消費者有時可能非常緩慢,我不想阻止生產者完成其他任務。這是否有助於潛在地提出一種替代方法來解決生產者在'synchronized(thrd1)'等待中等待的情況? – kmccoy

+1

在這種情況下,您可以使用中間線程安全的數據結構,如Queue。生產者將插入該隊列中,消費者將從那裏讀取。查看一些Queue實現的'java.util.concurrent'包,看看哪個最適合你。 – MondKin

0

建議的模式是使用notifyAll()AND以讓所有等待線程在每次通知它們並在開始第一次等待之前檢查它們的喚醒條件。

0

在現代Java中同步的速度差不多與--i一樣快,因爲這是關於硬件compareAndSet機制在內部發生的事情。唯一的情況是,當多於一個線程到達同步塊時,因此至少有一個線程必須等待。