線程中的通知和喚醒

wait()、notify()和notifyAll()是 Object類 中的方法java

從這三個方法的文字描述能夠知道如下幾點信息:安全

1)wait()、notify()和notifyAll()方法是本地方法,而且爲final方法,沒法被重寫。spa

2)調用某個對象的wait()方法能讓當前線程阻塞,而且當前線程必須擁有此對象的monitor(即鎖)線程

3)調用某個對象的notify()方法可以喚醒一個正在等待這個對象的monitor的線程,若是有多個線程都在等待這個對象的monitor,則只能喚醒其中一個線程;對象

4)調用notifyAll()方法可以喚醒全部正在等待這個對象的monitor的線程;繼承

有朋友可能會有疑問:爲什麼這三個不是Thread類聲明中的方法,而是Object類中聲明的方法(固然因爲Thread類繼承了Object類,因此 Thread也能夠調用者三個方法)?其實這個問題很簡單,因爲每一個對象都擁有monitor(即鎖),因此讓當前線程等待某個對象的鎖,固然應該經過這 個對象來操做了。而不是用當前線程來操做,由於當前線程可能會等待多個線程的鎖,若是經過線程來操做,就很是複雜了。接口

上面已經提到,若是調用某個對象的wait()方法,當前線程必須擁有這個對象的monitor(即鎖),所以調用wait()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)。隊列

調用某個對象的wait()方法,至關於讓當前線程交出此對象的monitor,而後進入等待狀態,等待後續再次得到此對象的鎖(Thread類中的sleep方法使當前線程暫停執行一段時間,從而讓其餘線程有機會繼續執行,但它並不釋放對象鎖);同步

notify()方法可以喚醒一個正在等待該對象的monitor的線程,當有多個線程都在等待該對象的monitor的話,則只能喚醒其中一個線程,具體喚醒哪一個線程則不得而知。it

一樣地,調用某個對象的notify()方法,當前線程也必須擁有這個對象的monitor,所以調用notify()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)。

nofityAll()方法可以喚醒全部正在等待該對象的monitor的線程,這一點與notify()方法是不一樣的。

Condition是在java 1.5中才出現的,它用來替代傳統的Object的wait()、notify()實現線程間的協做,相比使用Object的wait()、 notify(),使用Condition1的await()、signal()這種方式實現線程間協做更加安全和高效。所以一般來講比較推薦使用 Condition,在阻塞隊列那一篇博文中就講述到了,阻塞隊列其實是使用了Condition來模擬線程間協做。

  • Condition是個接口,基本的方法就是await()和signal()方法;
  • Condition依賴於Lock接口,生成一個Condition的基本代碼是lock.newCondition() 
  •  調用Condition的await()和signal()方法,都必須在lock保護以內,就是說必須在lock.lock()和lock.unlock之間纔可使用

Conditon中的await()對應Object的wait();

Condition中的signal()對應Object的notify();

Condition中的signalAll()對應Object的notifyAll()

相關文章
相關標籤/搜索