Java中notify()和notifyAll()的使用區別
notify() 和 notifyAll() 有什么區別?
先解釋兩個概念。 等待池:假設一個線程A調用了某個對象的wait()方法,線程A就會釋放該對象的鎖后,進入到了該對象的等待池,等待池中的線程不會去競爭該對象的鎖。 鎖池:只有獲取了對象的鎖,線程才能執行對象的 synchronized 代碼,對象的鎖每次只有一個線程可以獲得,其他線程只能在鎖池中等待然后再來說notify和notifyAll的區別 如果線程調用了對象的 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 RunnableImplAobj to wait on RunnableImplArun on RunnableImplAobj to wait on RunnableImplArun on RunnableImplB睡眠3秒...notify obj on RunnableImplBobj 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 RunnableImplAobj to wait on RunnableImplArun on RunnableImplAobj to wait on RunnableImplArun on RunnableImplC睡眠3秒...notifyAll obj on RunnableImplCobj continue to run on RunnableImplAobj continue to run on RunnableImplA
到此這篇關于Java中notify()和notifyAll()的使用區別的文章就介紹到這了,更多相關Java notify()和notifyAll()內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!
相關文章: