JAVA 線程通信相關(guān)知識匯總
兩個線程之間的通信
多線程環(huán)境下CPU會隨機的在線程之間進行切換,如果想讓兩個線程有規(guī)律的去執(zhí)行,那就需要兩個線程之間進行通信,在Object類中的兩個方法wait和notify可以實現(xiàn)通信。
wait方法可以使當(dāng)前線程進入到等待狀態(tài),在沒有被喚醒的情況下,線程會一直保持等待狀態(tài)。
notify方法可以隨機喚醒單個在等待狀態(tài)下的線程。
來實現(xiàn)這樣的一個功能:
讓兩個線程交替在控制臺輸出一行文字
定義一個Print類,有兩個方法print1和print2,分別打印一行不同的內(nèi)容
package com.sutaoyu.volatlt;
public class Print {
private int flag = 1;
public void print1() {
synchronized(this) {
if(flag != 1) {
try {
//讓當(dāng)前線程進入等入狀態(tài)
this.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("monkey");
flag = 2;
//隨機的喚醒單個等待的線程
this.notify();
}
}
public void print2() {
synchronized(this) {
if(flag != 2) {
try {
this.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println("1024");
flag = 1;
this.notify();
}
}
}
定義線程測試類,開啟兩個線程,分別運行Print類中print1和print2方法
package com.sutaoyu.volatlt;
public class NotifyTest01 {
public static void main(String[] args) {
Print p = new Print();
Thread t1 = new Thread() {
public void run() {
while(true) {
p.print1();
}
}
};
Thread t2 = new Thread() {
public void run() {
while(true) {
p.print2();
}
}
};
t1.start();
t2.start();
}
}
三個及三個以上的線程之間的通信
改造上面代碼在Print類中添加一個print3方法,再開啟第三個線程來執(zhí)行這個方法。
另外需要修改的地方是:
1.因為notifyAll方法可以喚醒所有等待狀態(tài)的線程,所有用notifyAll方法來替代notify方法
2.當(dāng)線程被喚醒后,需要先判斷一下flag的值,if不會重新判斷flag值,而while會重新判斷flag的值,所以將Print中的if判斷修改為while判斷。
package com.sutaoyu.volatlt;
public class Print {
private int flag = 1;
public void print1() {
synchronized(this) {
while(flag != 1) {
try {
//讓當(dāng)前線程進入等入狀態(tài)
this.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("monkey");
flag = 2;
//隨機的喚醒單個等待的線程
this.notifyAll();
}
}
public void print2() {
synchronized(this) {
while(flag != 2) {
try {
this.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println("1024");
flag = 3;
this.notifyAll();
}
}
public void print3() {
synchronized(this) {
while(flag != 3) {
try {
this.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("888");
flag = 1;
this.notifyAll();
}
}
}
package com.sutaoyu.volatlt;
public class NotifyTest01 {
public static void main(String[] args) {
Print p = new Print();
Thread t1 = new Thread() {
public void run() {
while(true) {
p.print1();
}
}
};
Thread t2 = new Thread() {
public void run() {
while(true) {
p.print2();
}
}
};
Thread t3 = new Thread() {
public void run() {
while(true) {
p.print3();
}
}
};
t1.start();
t2.start();
t3.start();
}
}
線程通信注意事項
在print1,2,3方法中同步代碼塊中使用哪個對象作為鎖,那在調(diào)用wait和notify方法時一定要調(diào)用這個對象上的wait和notify方法。
上面程序使用this作為對象鎖,在下面調(diào)用的都是this.wait()和this.notify()方法。
在多線程執(zhí)行當(dāng)中
wait方法釋放對象鎖,根據(jù)上面的代碼示例,t1,t2,t3三個線程使用的是同一個對象鎖,如果wait方法不釋放鎖的話,別的線程就不能獲取到該鎖,也就不能獲取cpu的執(zhí)行權(quán)了。
sleep和notify方法不釋放對象鎖,上面代碼示例中,如果notify方法釋放鎖的話,別的線程就有可能獲取到cpu的執(zhí)行權(quán),這樣子就會導(dǎo)致當(dāng)前notify方法后面的代碼還未執(zhí)行完畢就失去了cpu的執(zhí)行權(quán),從而導(dǎo)致一些問題,只有當(dāng)線程執(zhí)行完synchronized代碼塊后才會釋放鎖。
以上就是JAVA 線程通信相關(guān)知識匯總的詳細內(nèi)容,更多關(guān)于JAVA 線程通信的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
spring啟動錯誤Singleton bean creation not al
本文主要介紹了spring啟動錯誤Singleton bean creation not allowed while the singletons of this factory are indestruction,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
springboot?filter配置多個時,執(zhí)行順序問題
這篇文章主要介紹了springboot?filter配置多個時,執(zhí)行順序問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12

