舉個例子,如果你的Java程序中有兩個線程——即生產(chǎn)者和消費者,那么生產(chǎn)者可以通知消費者,讓消費者開始消耗數(shù)據(jù),因為隊列緩 沖區(qū)中有內(nèi)容待消費(不為空)。相應(yīng)的,消費者可以通知生產(chǎn)者可以開始生成更多的數(shù)據(jù),因為當(dāng)它消耗掉某些數(shù)據(jù)后緩沖區(qū)不再為滿。
jvm多個線程間的通信是通過 線程的鎖、條件語句、以及wait()、notify()/notifyAll組成。
wait()、notify()、notifyAll()是三個定義在Object類里的方法,可以用來控制線程的狀態(tài)。這三個方法最終調(diào)用的都是jvm級的native方法。
如果對象調(diào)用了wait方法就會使持有該對象的線程把該對象的控制權(quán)交出去,然后處于等待狀態(tài)。
如果對象調(diào)用了notify方法就會通知某個正在等待這個對象的控制權(quán)的線程可以繼續(xù)運行。
如果對象調(diào)用了notifyAll方法就會通知所有等待這個對象控制權(quán)的線程繼續(xù)運行。
利用wait()來讓一個線程在某些條件下暫停運行。
如果某些線程在等待某些條件觸發(fā),那當(dāng)那些條件為真時,你可以用 notify 和 notifyAll 來通知那些等待中的線程重新開始運行。不同之處在于,notify 僅僅通知一個線程,并且我們不知道哪個線程會收到通知,然而 notifyAll 會通知所有等待中的線程。換言之,如果只有一個線程在等待一個信號燈,notify和notifyAll都會通知到這個線程。但如果多個線程在等待這個信 號燈,那么notify只會通知到其中一個,而其它線程并不會收到任何通知,而notifyAll會喚醒所有等待中的線程。
永遠在循環(huán)(loop)里調(diào)用 wait 和 notify,不是在 If 語句。應(yīng)該永遠在 while循環(huán),而不是if語句中調(diào)用wait。在while循環(huán)里使用wait的目的,是在線程被喚醒的前后都持續(xù)檢查條件是否被滿足。如果條件并未改變,wait被調(diào)用之前notify的喚醒通知就來了,那么這個線程并不能保證被喚醒,有可能會導(dǎo)致死鎖問題
// The standard idiom for calling the wait method in Java
synchronized (sharedObject) {
while (condition) {
sharedObject.wait();
// (Releases lock, and reacquires on wakeup)
}
// do action based upon condition e.g. take or put into queue
}
《Java并發(fā)編程實戰(zhàn)》深入淺出地介紹了Java線程和并發(fā)