當乙個執行緒呼叫乙個共享變數的 wait() 方法時,該呼叫執行緒會被阻塞掛起,直到發生下面幾件事情之一才返回。
其他執行緒呼叫了該共享物件的 notify() 或者 notify() 方法;
其他執行緒呼叫了該執行緒的 interrupt() 方法,該執行緒丟擲 interruptedexception 異常返回。
注意:如果呼叫 wait() 方法的執行緒沒有事先獲取該物件的監視器鎖(synchronized),則呼叫wait() 方法時,呼叫執行緒會丟擲 illegalmonitorexception 異常。
乙個執行緒可以從掛起狀態變為可以執行狀態(也就被喚醒),即使該執行緒沒有被其他執行緒呼叫 notify() 、notifyall() 方法進行通知,或者被中斷,或者等待超時,這就是所謂的虛假喚醒。
避免虛假喚醒:不停地去測試該執行緒被喚醒的條件是否滿足,不滿足則繼續等待,也就是說在乙個迴圈中呼叫 wait() 方法進行防範,退出迴圈的條件是否滿足喚醒該執行緒的條件。
synchronized(obj)
}
首先通過同步塊獲取 obj 上面的監視器鎖,然後再 while 迴圈內呼叫 obj 的 wait()方法。
當前執行緒呼叫共享變數的 wait() 方法後只會釋放當前共享變數上的鎖,如果當前執行緒還持有其他共享變數的鎖,則這些鎖是不會被是釋放的。
public class waittest
}} catch (exception e)
}});
//建立執行緒
thread threadb = new thread(new runnable()
}} catch (exception e)
}});
//啟動執行緒
threada.start();
threadb.start();
//等待兩個執行緒結束
threada.join();
threadb.join();
system.out.println("main over");
}}
當乙個執行緒呼叫共享物件的 wait() 方法被阻塞掛起後,如果其他執行緒中斷了該執行緒,則執行緒會丟擲 interrupttedexception 異常並返回。
public class waitnotifyinterrupt
system.out.println("---結束---");
} catch (interruptedexception e)
}});
threada.start();
thread.sleep(1000);
system.out.println("開始中斷執行緒a");
threada.interrupt();
system.out.println("結束中斷執行緒a");
}}
如果乙個執行緒呼叫共享物件的該方法掛起後,沒有在指定的 timeout ms 時間內內被其他執行緒呼叫該共享變數的 notify() 或者 notifyall() 方法喚醒,那麼該函式還是會因為超時而返回。如果將 timeout 設定為 0 則和 wait 方法效果一樣,因為在 wait 方法內部就是呼叫了 wait(0)。需要注意的是,如果在呼叫該函式時,傳遞了乙個負的 timeout 則會丟擲 illegalargumentwexception 異常。
乙個執行緒呼叫共享物件的 notify() 方法後,會喚醒乙個在該共享變數上呼叫 wait 系列方法後被掛起的執行緒。乙個共享變數上可能會有多個執行緒在等待,具體喚醒哪個等待的執行緒是隨機的。
被喚醒的執行緒不能退馬上從 wait 方法返回並繼續執行,它必須在獲取了共享物件的監視器鎖後才可以返回,也就是喚醒它的執行緒釋放了共享變數上的監視器鎖後,被喚醒的執行緒也不一定會獲取到共享物件的監視器鎖,這是因為該執行緒還需要和其他執行緒一起競爭該鎖,只有該執行緒競爭到了共享變數的監視器鎖後才可以繼續執行。
類似 wait 系列方法,只有當執行緒獲取到了共享變數的監視器鎖後,才可以呼叫共享變數的 notify() 方法,否則會丟擲 illegalmonitorstateexception 異常
不同於在共享變數上呼叫 notify() 函式會喚醒被阻塞到該共享變數上的乙個執行緒,notifyall() 方法則會喚醒所有在該共享變數上由於 wait 系列方法而被掛起的執行緒。
public class waitnotify catch (interruptedexception e) }}
});//建立執行緒
thread threadb = new thread(new runnable() catch (interruptedexception e) }}
});//建立執行緒
thread threadc = new thread(new runnable()
}});
//啟動執行緒
threada.start();
threadb.start();
thread.sleep(1000);
threadc.start();
//等待執行緒結束
threada.join();
threadb.join();
threadc.join();
system.out.println("主線程結束。。。");
}}
執行緒通知與等待
乙個執行緒呼叫乙個共享變數的wait 方法時,該執行緒會被阻塞掛起。呼叫wait的前提是該執行緒有獲取共享變數的監視器鎖。獲取監視器鎖 1 synchronize 共享變數 2 在在共享變數的方法前加synchronize關鍵字,呼叫該方法。若執行緒沒有獲取監視器鎖而呼叫了wait 則會丟擲ille...
執行緒之間協作 等待與通知
在理解了執行緒之間可能存在相互衝突,以及怎樣避免衝突之後,下一步就是學習怎樣使線 程之間相互協作。這種協作關鍵是通過執行緒之間的握手來進行的,這種握手可以通過 object的方法wait 和notify 來安全的實現。呼叫sleep 的時候鎖並沒有被釋放,理解這一點很重要。另一方面,wait 方法的...
03 執行緒的通知notify與等待wait
wait notify notifyall 方法 wait notify notifyall 是三個定義在object類裡的方法,可以用來控制線程的狀態。這三個方法最終呼叫的都是jvm級的native方法。隨著jvm執行平台的不同可能有些許差異。public class notifyalldemo ...