您好,登錄后才能下訂單哦!
這篇文章主要講解了“Java中notify()和notifyAll()有哪些區別”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java中notify()和notifyAll()有哪些區別”吧!
等待池:假設一個線程A調用了某個對象的wait()方法,線程A就會釋放該對象的鎖后,進入到了該對象的等待池,等待池中的線程不會去競爭該對象的鎖。
鎖池:只有獲取了對象的鎖,線程才能執行對象的 synchronized 代碼,對象的鎖每次只有一個線程可以獲得,其他線程只能在鎖池中等待
如果線程調用了對象的 wait()方法,那么線程便會處于該對象的等待池中,等待池中的線程不會去競爭該對象的鎖。
當有線程調用了對象的 notifyAll()方法(喚醒所有 wait 線程)或 notify()方法(只隨機喚醒一個 wait 線程),被喚醒的的線程便會進入該對象的鎖池中,鎖池中的線程會去競爭該對象鎖。也就是說,調用了notify后只要一個線程會由等待池進入鎖池,而notifyAll會將該對象等待池內的所有線程移動到鎖池中,等待鎖競爭
優先級高的線程競爭到對象鎖的概率大,假若某線程沒有競爭到該對象鎖,它還會留在鎖池中,唯有線程再次調用 wait()方法,它才會重新回到等待池中。而競爭到對象鎖的線程則繼續往下執行,直到執行完了 synchronized 代碼塊,它會釋放掉該對象鎖,這時鎖池中的線程會繼續競爭該對象鎖。
綜上,所謂喚醒線程,另一種解釋可以說是將線程由等待池移動到鎖池,notifyAll調用后,會將全部線程由等待池移到鎖池,然后參與鎖的競爭,競爭成功則繼續執行,如果不成功則留在鎖池等待鎖被釋放后再次參與競爭。而notify只會喚醒一個線程。
有了這些理論基礎,后面的notify可能會導致死鎖,而notifyAll則不會的例子也就好解釋了
public class TestNotifyNotifyAll { private static Object obj = new Object(); public static void main(String[] args) { //測試 RunnableImplA wait() Thread t1 = new Thread(new RunnableImplA(obj)); Thread t2 = new Thread(new RunnableImplA(obj)); t1.start(); t2.start(); //RunnableImplB notify() Thread t3 = new Thread(new RunnableImplB(obj)); t3.start(); // //RunnableImplC notifyAll() // Thread t4 = new Thread(new RunnableImplC(obj)); // t4.start(); } } class RunnableImplA implements Runnable { private Object obj; public RunnableImplA(Object obj) { this.obj = obj; } public void run() { System.out.println("run on RunnableImplA"); synchronized (obj) { System.out.println("obj to wait on RunnableImplA"); try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("obj continue to run on RunnableImplA"); } } } class RunnableImplB implements Runnable { private Object obj; public RunnableImplB(Object obj) { this.obj = obj; } public void run() { System.out.println("run on RunnableImplB"); System.out.println("睡眠3秒..."); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj) { System.out.println("notify obj on RunnableImplB"); obj.notify(); } } } class RunnableImplC implements Runnable { private Object obj; public RunnableImplC(Object obj) { this.obj = obj; } public void run() { System.out.println("run on RunnableImplC"); System.out.println("睡眠3秒..."); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj) { System.out.println("notifyAll obj on RunnableImplC"); obj.notifyAll(); } } }
結果:僅調用一次 obj.notify(),線程 t1 或 t2 中的一個始終在等待被喚醒,程序不終止
run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplB
睡眠3秒...
notify obj on RunnableImplB
obj continue to run on RunnableImplA
把 t3 注掉,啟動 t4 線程。調用 obj.notifyAll() 方法
public class TestNotifyNotifyAll { private static Object obj = new Object(); public static void main(String[] args) { //測試 RunnableImplA wait() Thread t1 = new Thread(new RunnableImplA(obj)); Thread t2 = new Thread(new RunnableImplA(obj)); t1.start(); t2.start(); // //RunnableImplB notify() // Thread t3 = new Thread(new RunnableImplB(obj)); // t3.start(); //RunnableImplC notifyAll() Thread t4 = new Thread(new RunnableImplC(obj)); t4.start(); } }
結果:t1、t2線程均可以執行完畢
run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplC
睡眠3秒...
notifyAll obj on RunnableImplC
obj continue to run on RunnableImplA
obj continue to run on RunnableImplA
感謝各位的閱讀,以上就是“Java中notify()和notifyAll()有哪些區別”的內容了,經過本文的學習后,相信大家對Java中notify()和notifyAll()有哪些區別這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。