1、wait()、notify/notifyAll() 方法是Object的本地final方法,無法被重寫。
2、wait()使當前線程阻塞,前提是 必須先獲得鎖,一般配合synchronized 關鍵字使用,即,一般在synchronized 同步代碼塊裏使用 wait()、notify/notifyAll() 方法。
3、 由於 wait()、notify/notifyAll() 在synchronized 代碼塊執行,說明當前線程一定是獲取了鎖的。當線程執行wait()方法時候,會釋放當前的鎖,然後讓出CPU,進入等待狀態。
只有當 notify/notifyAll() 被執行時候,纔會喚醒一個或多個正處於等待狀態的線程,然後繼續往下執行,直到執行完synchronized 代碼塊的代碼或是中途遇到wait() ,再次釋放鎖。
也就是說,notify/notifyAll() 的執行只是喚醒沉睡的線程,而不會立即釋放鎖,鎖的釋放要看代碼塊的具體執行情況。所以在編程中,儘量在使用了notify/notifyAll() 後立即退出臨界區,以喚醒其他線程讓其獲得鎖
4、wait() 需要被try catch包圍,以便發生異常中斷也可以使wait等待的線程喚醒。
5、notify 和wait 的順序不能錯,如果A線程先執行notify方法,B線程在執行wait方法,那麼B線程是無法被喚醒的。
6、notify 和 notifyAll的區別
notify方法只喚醒一個等待(對象的)線程並使該線程開始執行。所以如果有多個線程等待一個對象,這個方法只會喚醒其中一個線程,選擇哪個線程取決於操作系統對多線程管理的實現。notifyAll 會喚醒所有等待(對象的)線程,儘管哪一個線程將會第一個處理取決於操作系統的實現。如果當前情況下有多個線程需要被喚醒,推薦使用notifyAll 方法。比如在生產者-消費者裏面的使用,每次都需要喚醒所有的消費者或是生產者,以判斷程序是否可以繼續往下執行。
7、在多線程中要測試某個條件的變化,使用if 還是while?
要注意,notify喚醒沉睡的線程後,線程會接着上次的執行繼續往下執行。所以在進行條件判斷時候,可以先把 wait 語句忽略不計來進行考慮;顯然,要確保程序一定要執行,並且要保證程序直到滿足一定的條件再執行,要使用while進行等待,直到滿足條件才繼續往下執行。如下代碼:
public class K {
//狀態鎖
private Object lock;
//條件變量
private int now,need;
public void produce(int num){
//同步
synchronized (lock){
//當前有的不滿足需要,進行等待,直到滿足條件
while(now < need){
try {
//等待阻塞
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我被喚醒了!");
}
// 做其他的事情
}
}
}
顯然,只有當前值滿足需要值的時候,線程纔可以往下執行,所以,必須使用while 循環阻塞。注意,wait() 當被喚醒時候,只是讓while循環繼續往下走.如果此處用if的話,意味着if繼續往下走,會跳出if語句塊。