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

