java 中線程等待與通知的實(shí)現(xiàn)
java 中線程等待與通知的實(shí)現(xiàn)
前言:
關(guān)于等待/通知,要記住的關(guān)鍵點(diǎn)是:
必須從同步環(huán)境內(nèi)調(diào)用wait()、notify()、notifyAll()方法。線程不能調(diào)用對象上等待或通知的方法,除非它擁有那個(gè)對象的鎖。
wait()、notify()、notifyAll()都是Object的實(shí)例方法。與每個(gè)對象具有鎖一樣,每個(gè)對象可以有一個(gè)線程列表,他們等待來自該信號(hào)(通知)。線程通過執(zhí)行對象上的wait()方法獲得這個(gè)等待列表。從那時(shí)候起,它不再執(zhí)行任何其他指令,直到調(diào)用對象的notify()方法為止。如果多個(gè)線程在同一個(gè)對象上等待,則將只選擇一個(gè)線程(不保證以何種順序)繼續(xù)執(zhí)行。如果沒有線程等待,則不采取任何特殊操作。
示例代碼:
package threadwait; public class ThreadA extends Thread{ public int num = 0; public void run(){ synchronized (this){//在此類對象上實(shí)現(xiàn)同步,this指代當(dāng)前對象 for(int i = 0 ; i < 3 ; ++i) this.num+=i; notifyAll();//通知所有在這個(gè)對象上等待的線程開始執(zhí)行,在這里就是通知TestNotify主線程開始執(zhí)行 } } public int getNum(){ return this.num; } }
package threadwait; public class TestNotify{ public static void main(String args[]){ ThreadA threada = new ThreadA(); threada.start();//threada線程有執(zhí)行的資格,但是還沒有開始執(zhí)行 synchronized(threada){ try{ threada.wait();//主線程等待threada線程執(zhí)行結(jié)束才開始執(zhí)行 //而且只有獲得了當(dāng)前threada對象的鎖之后才能執(zhí)行wait,就是說在同步域內(nèi)才可以執(zhí)行wait,執(zhí)行wait后放棄對象鎖 }catch(InterruptedException e){ e.printStackTrace(); } } System.out.println(threada.getNum()); } }
同步可以是在class級(jí)別上的,synchronized(A.class),也可以是在對象級(jí)別上的synchronized(this),可以是靜態(tài)同步方法,static synchronized ,靜態(tài)同步方法是在class級(jí)別上的,非靜態(tài)同步方法是在類對象級(jí)別上的,一個(gè)類對象只有一個(gè)鎖,只有獲得了該鎖才可以對他執(zhí)行wait操作,后釋放掉該鎖。
更進(jìn)一步的實(shí)例代碼如下:
package threadwait; public class ThreadA extends Thread{ public int num = 0; public void run(){ synchronized (this){//在此類對象上實(shí)現(xiàn)同步,this指代當(dāng)前對象 for(int i = 0 ; i < 3 ; ++i) this.num+=i; try{ Thread.sleep(500);//如果ThreadB的三個(gè)示例線程在還沒有進(jìn)入等待狀態(tài)之前就受到了notifyall的信號(hào) //那將會(huì)發(fā)生嚴(yán)重后果,因?yàn)檎{(diào)用notifyall的線程只可以調(diào)用一次notifyall,那造成等待的線程將永遠(yuǎn)等待下去 //所以在此處讓它睡一小會(huì),讓其他線程有時(shí)間進(jìn)入等待狀態(tài)。 //不然會(huì)收到 }catch(InterruptedException e){ e.printStackTrace(); } notifyAll();//通知所有在這個(gè)對象上等待的線程開始執(zhí)行,在這里就是通知TestNotify主線程開始執(zhí)行 } // notifyAll(); } public int getNum(){ return this.num; } }
package threadwait; public class ThreadB extends Thread{ private ThreadA threada; public ThreadB(ThreadA ta){ this.threada = ta; } public void run(){ System.out.println(Thread.currentThread().getName()+" is waitting."); synchronized(threada){ try{ threada.wait(); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" "+this.threada.getNum()); } } }
package threadwait; public class TestNotify{ public static void main(String args[]){ ThreadA threada = new ThreadA(); new ThreadB(threada).start(); new ThreadB(threada).start(); new ThreadB(threada).start(); threada.start(); } }
如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
如何解決websocket開啟多個(gè)頁面訪問同一個(gè)連接會(huì)失效的問題
使用WebSocket時(shí),若多個(gè)頁面訪問同一個(gè)WebSocket連接可能會(huì)導(dǎo)致連接失效,遇到這個(gè)問題時(shí),可以通過在SpringBoot中使用@ServerEndpoint注解并添加@Component來解決,出現(xiàn)連接錯(cuò)誤通常是因?yàn)閃ebSocket連接接收到的是一個(gè)GET請求2024-09-09Spring內(nèi)部bean和級(jí)聯(lián)屬性用法詳解
這篇文章主要介紹了Java內(nèi)部bean和級(jí)聯(lián)屬性用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10Java數(shù)據(jù)結(jié)構(gòu)之雙向鏈表圖解
這篇文章主要為大家詳細(xì)介紹了Java數(shù)據(jù)結(jié)構(gòu)之雙向鏈表,文中圖解分析的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05idea中增強(qiáng)for循環(huán)提示unexpected token問題
這篇文章主要介紹了idea中增強(qiáng)for循環(huán)提示unexpected token問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01Java中調(diào)用第三方接口的幾種方法詳細(xì)指南
在Java開發(fā)中調(diào)用第三方接口是常見需求,本文介紹如何使用Java進(jìn)行接口調(diào)用,重點(diǎn)講解HttpURLConnection類、OkHttp庫和ApacheHttpClient的使用,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-10-10使用Feign設(shè)置Token鑒權(quán)調(diào)用接口
這篇文章主要介紹了使用Feign設(shè)置Token鑒權(quán)調(diào)用接口,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03SpringMVC中控制器返回JSON數(shù)據(jù)的實(shí)現(xiàn)
本文主要介紹了SpringMVC中控制器返回JSON數(shù)據(jù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07java中JDBC實(shí)現(xiàn)往MySQL插入百萬級(jí)數(shù)據(jù)的實(shí)例代碼
這篇文章主要介紹了java中JDBC實(shí)現(xiàn)往MySQL插入百萬級(jí)數(shù)據(jù)的實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-01-01SpringBoot?+?Vue?+?ElementUI?實(shí)現(xiàn)?el-table?分頁功能(詳細(xì)步驟)
本文詳細(xì)介紹了使用SpringBoot和Vue.js結(jié)合ElementUI實(shí)現(xiàn)分頁功能的數(shù)據(jù)表格,從后端分頁邏輯到前端展示和狀態(tài)管理,全面解析如何高效處理大量數(shù)據(jù),提升用戶體驗(yàn)與系統(tǒng)性能,感興趣的朋友跟隨小編一起看看吧2024-09-09Spring Boot 動(dòng)態(tài)數(shù)據(jù)源示例(多數(shù)據(jù)源自動(dòng)切換)
本篇文章主要介紹了Spring Boot 動(dòng)態(tài)數(shù)據(jù)源示例(多數(shù)據(jù)源自動(dòng)切換),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-02-02