Java多線(xiàn)程通訊之wait,notify的區(qū)別詳解
下面通過(guò)代碼給大家介紹java多線(xiàn)程通訊之wait notify的區(qū)別,具體內(nèi)容如下所示:
class Res{
public String username;
public String sex;
}
class Out extends Thread{
Res res;
public Out(Res res){
this.res=res;
}
@Override
public void run() {
//寫(xiě)操作
int count=0;
while (true){
// synchronized (res.getClass()){
if(count==0){//偶數(shù)
res.username="小明";
res.sex="男";
} else {//奇數(shù)
res.username="小紅";
res.sex="女";
}
count=(count+1)%2;
// }
}
}
}
class Input extends Thread{
Res res;
public Input(Res res){
this.res=res;
}
@Override
public void run() {
while (true){
// synchronized (res.getClass()){
System.out.println(res.username+","+res.sex);
// }
}
}
}
public class OutInputThread {
public static void main(String[] args) {
Res res = new Res();
Out out = new Out(res);
Input input = new Input(res);
out.start();
input.start();
}
}
小紅,女
小紅,女
小紅,女
小紅,女
小紅,女
小紅,女
小紅,女
小紅,女
小紅,女
出現(xiàn)以上結(jié)果??消費(fèi)者一直消費(fèi)或者生產(chǎn)者一直生產(chǎn)
解決方法:生產(chǎn)者生產(chǎn)完成后消費(fèi)者方可消費(fèi),否者不可消費(fèi),消費(fèi)者未消費(fèi)或者未消費(fèi)完生產(chǎn)者不可生產(chǎn),一次生產(chǎn)一次消費(fèi)。其實(shí)也就是保證對(duì)res共享資源的操作同一時(shí)刻僅有同一個(gè)線(xiàn)程進(jìn)行操作,
wait、notify、notifyAll方法
wait、notify、notifyAll是三個(gè)定義在Object類(lèi)里的方法,可以用來(lái)控制線(xiàn)程的狀態(tài)。
這三個(gè)方法最終調(diào)用的都是jvm級(jí)的native方法。隨著jvm運(yùn)行平臺(tái)的不同可能有些許差異。
如果對(duì)象調(diào)用了wait方法就會(huì)使持有該對(duì)象的線(xiàn)程把該對(duì)象的控制權(quán)交出去,然后處于等待狀態(tài)。當(dāng)前線(xiàn)程從運(yùn)行變?yōu)樽枞?,釋放所的資源
如果對(duì)象調(diào)用了notify方法就會(huì)通知某個(gè)正在等待這個(gè)對(duì)象的控制權(quán)的線(xiàn)程可以繼續(xù)運(yùn)行。讓持有該鎖的線(xiàn)程從阻塞態(tài)變?yōu)榫途w。
如果對(duì)象調(diào)用了notifyAll方法就會(huì)通知所有等待這個(gè)對(duì)象控制權(quán)的線(xiàn)程繼續(xù)運(yùn)行。
注意:一定要在線(xiàn)程同步中使用,并且是同一個(gè)鎖的資源
通過(guò)以下方式即可完成需求。
生產(chǎn)者獲取res.getClass鎖后,如果flag為true生產(chǎn)者通過(guò)調(diào)用res.getClass.wait進(jìn)行等待,此時(shí)其他線(xiàn)程可獲取該鎖,如果flag為false,進(jìn)行生產(chǎn),然后設(shè)置flag為true保證資源消費(fèi)后方可再生產(chǎn),接著通過(guò)notify通知其他喚醒其他線(xiàn)程。
class Res{
public String username;
public String sex;
//true 生產(chǎn)者等待,消費(fèi)者可消費(fèi) false生產(chǎn)者可以生產(chǎn),消費(fèi)者不可消費(fèi)
public boolean flag=false;
}
class Out extends Thread{
Res res;
public Out(Res res){
this.res=res;
}
@Override
public void run() {
//寫(xiě)操作
int count=0;
while (true){
synchronized (res.getClass()){
if(res.flag){
try {
res.getClass().wait();//讓當(dāng)前線(xiàn)程從運(yùn)行變?yōu)樽枞?,并且釋放所的資源
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(count==0){//偶數(shù)
res.username="小明";
res.sex="男";
} else {//奇數(shù)
res.username="小紅";
res.sex="女";
}
count=(count+1)%2;
res.flag=true;
res.getClass().notify();
}
}
}
}
class Input extends Thread{
Res res;
public Input(Res res){
this.res=res;
}
@Override
public void run() {
while (true){
synchronized (res.getClass()){
if(!res.flag){
try {
res.getClass().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(res.username+","+res.sex);
res.flag=false;
res.getClass().notify();
}
}
}
}
public class OutInputThread {
public static void main(String[] args) {
Res res = new Res();
Out out = new Out(res);
Input input = new Input(res);
out.start();
input.start();
}
}
輸出如下:
小明,男
小紅,女
小明,男
小紅,女
小明,男
小紅,女
小明,男
小紅,女
如果去掉notify會(huì)怎樣?去掉一個(gè)?去掉兩個(gè)?
去掉一個(gè)生產(chǎn)者可以打印多個(gè)(但是也不多),去掉消費(fèi)者僅可打印一個(gè),去掉兩個(gè)可能不打印,也可能打印1個(gè),所以wait、notify必須成對(duì)使用
wait(用于同步中)與sleep區(qū)別?
都是做休眠,wait需要notify
對(duì)于sleep方法,我們首先要知道該方法是屬于Thread類(lèi)中的。而wait方法,則是屬于Object類(lèi)中的。
sleep方法導(dǎo)致了程序暫停執(zhí)行指定的時(shí)間,讓出cpu該其他線(xiàn)程,但是他的監(jiān)控狀態(tài)依然保持者,當(dāng)指定的時(shí)間到了又會(huì)自動(dòng)恢復(fù)運(yùn)行狀態(tài)。
在調(diào)用sleep方法的過(guò)程中,線(xiàn)程不會(huì)釋放對(duì)象鎖。
而當(dāng)調(diào)用wait方法的時(shí)候,線(xiàn)程會(huì)放棄對(duì)象鎖,進(jìn)入等待此對(duì)象的等待鎖定池,只有針對(duì)此對(duì)象調(diào)用notify方法后本線(xiàn)程才進(jìn)入對(duì)象鎖定池準(zhǔn)備獲取對(duì)象鎖進(jìn)入運(yùn)行狀態(tài)。
總結(jié)
以上所述是小編給大家介紹的Java多線(xiàn)程通訊之wait,notify的區(qū)別詳解,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
JAVA實(shí)現(xiàn)基于Tcp協(xié)議的簡(jiǎn)單Socket通信實(shí)例
本篇文章主要介紹了JAVA實(shí)現(xiàn)基于Tcp協(xié)議的簡(jiǎn)單Socket通信實(shí)例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01
async-excel實(shí)現(xiàn)多sheet異步導(dǎo)出方法詳解
這篇文章主要介紹了async-excel實(shí)現(xiàn)多sheet異步導(dǎo)出方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12
Gitlab CI-CD自動(dòng)化部署SpringBoot項(xiàng)目的方法步驟
本文主要記錄如何通過(guò)Gitlab CI/CD自動(dòng)部署SpringBoot項(xiàng)目jar包。文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07
java樹(shù)結(jié)構(gòu)stream工具類(lèi)的示例代碼詳解
Stream 作為 Java 8 的一大亮點(diǎn),它與 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。今天通過(guò)本文重點(diǎn)給大家介紹java樹(shù)結(jié)構(gòu)stream工具類(lèi)的示例代碼,感興趣的朋友一起看看吧2022-03-03
解決Jenkins集成SonarQube遇到的報(bào)錯(cuò)問(wèn)題
本文給大家分享Jenkins集成SonarQube遇到的報(bào)錯(cuò)問(wèn)題及解決方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-07-07
SpringBoot_Cache自定義使用SimpleCacheManager方式
這篇文章主要介紹了SpringBoot_Cache自定義使用SimpleCacheManager方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
Java身份證號(hào)碼校驗(yàn)工具類(lèi)詳解
這篇文章主要為大家詳細(xì)介紹了Java身份證號(hào)碼校驗(yàn)工具類(lèi),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10
Java中定時(shí)器Timer致命缺點(diǎn)案例詳解
這篇文章主要介紹了Java中定時(shí)器Timer致命缺點(diǎn),以Java中定時(shí)器Time為案例整理下我的學(xué)習(xí)方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02
解決idea中javaweb的mysql8.0.15配置問(wèn)題
這篇文章主要介紹了idea中javaweb的mysql8.0.15配置問(wèn)題 ,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05

