2017-05-08 60 views
0

我有一個線程,當它運行時,它創建一個Message對象,放入監視器的鏈表中。與此同時,另外兩個線程等待這個列表獲取一個Message對象,在一段時間(linkedlist.isEmpty())canGetMessage.await();循環,但即使我發送canGetMessage.signalAll();命令將對象放入列表中時,其他兩個線程都不會喚醒。線程條件不會醒來

public void deliverMessage(Message m){ 
lock.lock(); 

try{ 
    linkedlist.add(m); 
    canGetMessage.signalAll(); 
}finally{ 
    lock.unlock(); 
} 
} 


public Message getMessage(){ 
lock.lock(); 

try{ 
while(linkedlist.isEmpty()){ 
    canGetMessage.await(); 
    } 
return linkedlist.remove(); //returns the item that has been in the list the longest 
} 
catch (InterruptedException e) { } //not required to handle these 

finally{ 
lock.unlock(); 
} 

我已經調用println看到它的時候失控while循環,但是這永遠不會發生,我不知道爲什麼...

編輯:只是爲了說明,鎖我m使用的是ReentrantLock

+2

你爲什麼不使用生產者 - 消費者模式的BlockingQueue? –

+1

發佈一個完整的重現問題的最小示例。 –

+0

'lock','linkedlist'和'canGetMessage'是什麼類型的,它們是如何創建的?而且,是的,[MCVE](http://stackoverflow.com/help/mcve)將會非常有用。 – yeputons

回答

0

猜測;你在這裏有問題:

lock.lock(); 

如果發送/接收器使用相同的對象,這可不行。收貨人收購鎖;並且直到發件人向列表中添加新條目纔會釋放它。

但發件人無法進入該部分;因爲發件人試圖在已鎖定的鎖上鎖定。所以鎖定的鎖將被阻止。

「正確的」答案是使用BlockingQueue連接發件人/收件人 - 而不是重新發明「像隊列」的東西。有關更多資料,請參閱here如何使用BlockingQueue。

+1

不,canGetMessage.await()釋放鎖(假設條件已經從該鎖創建)。 –

+0

可能...讓我們看看OP說的是什麼。如果它不幫助他,我不介意刪除答案。 – GhostCat

+2

@Telanore你不應該使用一個單獨的鎖。如果你想要一個解釋,發佈一個完整的例子來重現問題。或者繼續前進並使用BlockingQueue(我同意這是一個更好的解決方案)。 –

0

我給大家道歉,原來問題在創造自己,我無意中爲每個線程使用同一個,而不是讓他們所有的獨立的監視器線程的躺在...

+1

你要麼改善問題和自我回答...或者可能刪除你的問題。 – GhostCat