Java中notify()和notifyAll()的使用區(qū)別
notify() 和 notifyAll() 有什么區(qū)別?
先解釋兩個(gè)概念。 等待池:假設(shè)一個(gè)線(xiàn)程A調(diào)用了某個(gè)對(duì)象的wait()方法,線(xiàn)程A就會(huì)釋放該對(duì)象的鎖后,進(jìn)入到了該對(duì)象的等待池,等待池中的線(xiàn)程不會(huì)去競(jìng)爭(zhēng)該對(duì)象的鎖。 鎖池:只有獲取了對(duì)象的鎖,線(xiàn)程才能執(zhí)行對(duì)象的 synchronized 代碼,對(duì)象的鎖每次只有一個(gè)線(xiàn)程可以獲得,其他線(xiàn)程只能在鎖池中等待然后再來(lái)說(shuō)notify和notifyAll的區(qū)別 如果線(xiàn)程調(diào)用了對(duì)象的 wait()方法,那么線(xiàn)程便會(huì)處于該對(duì)象的等待池中,等待池中的線(xiàn)程不會(huì)去競(jìng)爭(zhēng)該對(duì)象的鎖。 當(dāng)有線(xiàn)程調(diào)用了對(duì)象的 notifyAll()方法(喚醒所有 wait 線(xiàn)程)或 notify()方法(只隨機(jī)喚醒一個(gè) wait 線(xiàn)程),被喚醒的的線(xiàn)程便會(huì)進(jìn)入該對(duì)象的鎖池中,鎖池中的線(xiàn)程會(huì)去競(jìng)爭(zhēng)該對(duì)象鎖。也就是說(shuō),調(diào)用了notify后只要一個(gè)線(xiàn)程會(huì)由等待池進(jìn)入鎖池,而notifyAll會(huì)將該對(duì)象等待池內(nèi)的所有線(xiàn)程移動(dòng)到鎖池中,等待鎖競(jìng)爭(zhēng) 優(yōu)先級(jí)高的線(xiàn)程競(jìng)爭(zhēng)到對(duì)象鎖的概率大,假若某線(xiàn)程沒(méi)有競(jìng)爭(zhēng)到該對(duì)象鎖,它還會(huì)留在鎖池中,唯有線(xiàn)程再次調(diào)用 wait()方法,它才會(huì)重新回到等待池中。而競(jìng)爭(zhēng)到對(duì)象鎖的線(xiàn)程則繼續(xù)往下執(zhí)行,直到執(zhí)行完了 synchronized 代碼塊,它會(huì)釋放掉該對(duì)象鎖,這時(shí)鎖池中的線(xiàn)程會(huì)繼續(xù)競(jìng)爭(zhēng)該對(duì)象鎖。綜上,所謂喚醒線(xiàn)程,另一種解釋可以說(shuō)是將線(xiàn)程由等待池移動(dòng)到鎖池,notifyAll調(diào)用后,會(huì)將全部線(xiàn)程由等待池移到鎖池,然后參與鎖的競(jìng)爭(zhēng),競(jìng)爭(zhēng)成功則繼續(xù)執(zhí)行,如果不成功則留在鎖池等待鎖被釋放后再次參與競(jìng)爭(zhēng)。而notify只會(huì)喚醒一個(gè)線(xiàn)程。
有了這些理論基礎(chǔ),后面的notify可能會(huì)導(dǎo)致死鎖,而notifyAll則不會(huì)的例子也就好解釋了
測(cè)試代碼public class TestNotifyNotifyAll { private static Object obj = new Object(); public static void main(String[] args) { //測(cè)試 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(); } }}
結(jié)果:僅調(diào)用一次 obj.notify(),線(xiàn)程 t1 或 t2 中的一個(gè)始終在等待被喚醒,程序不終止
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 注掉,啟動(dòng) t4 線(xiàn)程。調(diào)用 obj.notifyAll() 方法
public class TestNotifyNotifyAll { private static Object obj = new Object(); public static void main(String[] args) { //測(cè)試 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(); } }
結(jié)果:t1、t2線(xiàn)程均可以執(zhí)行完畢
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
到此這篇關(guān)于Java中notify()和notifyAll()的使用區(qū)別的文章就介紹到這了,更多相關(guān)Java notify()和notifyAll()內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. PHP使用Swagger生成好看的API文檔2. ASP.NET MVC使用jQuery ui的progressbar實(shí)現(xiàn)進(jìn)度條3. Python3 json模塊之編碼解碼方法講解4. Python 制作查詢(xún)商品歷史價(jià)格的小工具5. Python 如何調(diào)試程序崩潰錯(cuò)誤6. Python 利用Entrez庫(kù)篩選下載PubMed文獻(xiàn)摘要的示例7. ASP基礎(chǔ)知識(shí)VBScript基本元素講解8. python使用jenkins發(fā)送企業(yè)微信通知的實(shí)現(xiàn)9. Python sublime安裝及配置過(guò)程詳解10. Python 合并拼接字符串的方法

網(wǎng)公網(wǎng)安備