java 中線程等待與通知的實現(xiàn)
java 中線程等待與通知的實現(xiàn)
前言:
關(guān)于等待/通知,要記住的關(guān)鍵點是:
必須從同步環(huán)境內(nèi)調(diào)用wait()、notify()、notifyAll()方法。線程不能調(diào)用對象上等待或通知的方法,除非它擁有那個對象的鎖。
wait()、notify()、notifyAll()都是Object的實例方法。與每個對象具有鎖一樣,每個對象可以有一個線程列表,他們等待來自該信號(通知)。線程通過執(zhí)行對象上的wait()方法獲得這個等待列表。從那時候起,它不再執(zhí)行任何其他指令,直到調(diào)用對象的notify()方法為止。如果多個線程在同一個對象上等待,則將只選擇一個線程(不保證以何種順序)繼續(xù)執(zhí)行。如果沒有線程等待,則不采取任何特殊操作。
示例代碼:
package threadwait;
public class ThreadA extends Thread{
public int num = 0;
public void run(){
synchronized (this){//在此類對象上實現(xiàn)同步,this指代當(dāng)前對象
for(int i = 0 ; i < 3 ; ++i)
this.num+=i;
notifyAll();//通知所有在這個對象上等待的線程開始執(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級別上的,synchronized(A.class),也可以是在對象級別上的synchronized(this),可以是靜態(tài)同步方法,static synchronized ,靜態(tài)同步方法是在class級別上的,非靜態(tài)同步方法是在類對象級別上的,一個類對象只有一個鎖,只有獲得了該鎖才可以對他執(zhí)行wait操作,后釋放掉該鎖。
更進一步的實例代碼如下:
package threadwait;
public class ThreadA extends Thread{
public int num = 0;
public void run(){
synchronized (this){//在此類對象上實現(xiàn)同步,this指代當(dāng)前對象
for(int i = 0 ; i < 3 ; ++i)
this.num+=i;
try{
Thread.sleep(500);//如果ThreadB的三個示例線程在還沒有進入等待狀態(tài)之前就受到了notifyall的信號
//那將會發(fā)生嚴(yán)重后果,因為調(diào)用notifyall的線程只可以調(diào)用一次notifyall,那造成等待的線程將永遠(yuǎn)等待下去
//所以在此處讓它睡一小會,讓其他線程有時間進入等待狀態(tài)。
//不然會收到
}catch(InterruptedException e){
e.printStackTrace();
}
notifyAll();//通知所有在這個對象上等待的線程開始執(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)文章
Java基于JDBC實現(xiàn)事務(wù),銀行轉(zhuǎn)賬及貨物進出庫功能示例
這篇文章主要介紹了Java基于JDBC實現(xiàn)事務(wù),銀行轉(zhuǎn)賬及貨物進出庫功能,較為詳細(xì)的分析了事務(wù)操作的原理、實現(xiàn)方法及java基于jdbc連接數(shù)據(jù)庫實現(xiàn)銀行事務(wù)操作的相關(guān)技巧,需要的朋友可以參考下2017-12-12
alibaba?seata服務(wù)端具體實現(xiàn)
seata是來處理分布式服務(wù)之間互相調(diào)用的事務(wù)問題,本文重點給大家介紹alibaba-seata實現(xiàn)方法,文中通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02
劍指Offer之Java算法習(xí)題精講數(shù)組與字符串題
跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會發(fā)現(xiàn)質(zhì)的變化2022-03-03

