聊聊Object類(lèi)中的wait()和notify()方法
Object類(lèi)中的wait()和notify()方法
一、特點(diǎn)
wait()和notify()方法并不是線程對(duì)象的方法,是Java中任何一個(gè)Java對(duì)象都有的方法,并不特殊。
二、wait()方法的作用
Object obj = new Object(); obj.wait();
表示:obj.wait();方法的調(diào)用,會(huì)讓“當(dāng)前線程(正在obj對(duì)象上活動(dòng)的線程)”進(jìn)入等待狀態(tài)。
三、notify()方法的作用
Object obj = new Object(); obj.notify();
表示:?jiǎn)拘颜趏bj對(duì)象上等待的線程。
補(bǔ)充:
Object obj = new Object(); obj.notifyAll();
表示:?jiǎn)拘颜趏bj對(duì)象上等待的所有線程。
四、wait()和notify()的使用
wait()和notify()方法都是建立在synchronized線程同步的基礎(chǔ)之上
重點(diǎn)
obj.wait()方法會(huì)讓正在obj對(duì)象上活動(dòng)的當(dāng)前線程進(jìn)入等待狀態(tài),并且釋放之前占有的obj對(duì)象的鎖。
obj.notify()方法只會(huì)通知,不會(huì)釋放之前占有的obj對(duì)象的鎖。
object中的wait和notify細(xì)節(jié)
wait
jdk源碼:

重點(diǎn)看下劃線的地方,是不是有些不理解。有個(gè)印象我們繼續(xù)往下看。
public class resourse {
private Integer number = 0 ;
/**
* 用if為啥不行
* 1:首先一點(diǎn)我們要搞清楚 wait操作會(huì)釋放鎖
* 2:想想這種情況,當(dāng)一個(gè)生產(chǎn)者線程執(zhí)行的時(shí)候 if number!=0 (此時(shí)的number為1 ) 就會(huì)發(fā)生阻塞 這時(shí)候
* 釋放出鎖 這時(shí)候又一個(gè)生產(chǎn)者進(jìn)程進(jìn)來(lái)又會(huì)被wait住.然后一個(gè)生產(chǎn)者進(jìn)程進(jìn)來(lái),消費(fèi)了一個(gè) 但是notifyall 將所有的進(jìn)程
* 都解開(kāi)了 。。那兩個(gè)生產(chǎn)者進(jìn)程就會(huì)直接運(yùn)行if后面的東西并沒(méi)有被拉回來(lái)重新判斷一下。這樣就造成了number的值變成2.同理number
* 變成負(fù)數(shù)也是有可能的(兩個(gè)消費(fèi)者進(jìn)程先進(jìn)來(lái)都堵塞).
*
*
*
*
* @throws Exception
*/
public synchronized void produce () throws Exception
{
// 判斷 這里用while 用if多與兩個(gè)線程容易出錯(cuò)
// 不等于0就要等待消費(fèi)者消費(fèi)完
if(number!=0)
{
this.wait();
}
// 干活
number++;
System.out.println(Thread.currentThread().getName() + "的資源數(shù)為:" + number.toString());
// 釋放
this.notifyAll();
}
//wait操作會(huì)釋放鎖
public synchronized void consumer () throws Exception
{
// 等于零就要等待生產(chǎn)者生產(chǎn)
if (number == 0)
{
this.wait();
}
// 消費(fèi)
number--;
System.out.println(Thread.currentThread().getName() + "的資源數(shù)為:" + number.toString());
// 釋放
this.notifyAll();
}
}
調(diào)用者。這里開(kāi)啟了兩個(gè)生產(chǎn)者和兩個(gè)消費(fèi)者線程。生產(chǎn)者線程都執(zhí)行100次的produce,消費(fèi)者線程都執(zhí)行100次的consumer
public class main {
public static void main (String[] args) {
resourse resourse = new resourse();
new Thread(()->{
try{
for (int i=0 ; i<100;i++)
resourse.produce();
}catch (Exception e)
{
e.printStackTrace();
}
}).start();
new Thread(()->{
try{
for (int i=0 ; i<100;i++)
resourse.produce();
}catch (Exception e)
{
e.printStackTrace();
}
}).start();
new Thread(()->{
try{
for (int i=0 ; i<100;i++)
resourse.consumer();
}catch (Exception e)
{
e.printStackTrace();
}
}).start();
new Thread(()->{
try{
for (int i=0 ; i<100;i++)
resourse.consumer();
}catch (Exception e)
{
e.printStackTrace();
}
}).start();
}
}
我要說(shuō)的重點(diǎn)是:

這樣設(shè)計(jì)真的合理嗎?
jdk中為啥要規(guī)定我們要使用while,而不是if?
用if為啥不行
1:首先一點(diǎn)我們要搞清楚 wait操作會(huì)釋放鎖
2:想想這種情況,當(dāng)一個(gè)生產(chǎn)者線程執(zhí)行的時(shí)候 if number!=0 (此時(shí)的number為1 ) 就會(huì)發(fā)生阻塞 這時(shí)候釋放出鎖 這時(shí)候又一個(gè)生產(chǎn)者進(jìn)程進(jìn)來(lái)又會(huì)被wait住.然后一個(gè)生產(chǎn)者進(jìn)程進(jìn)來(lái),消費(fèi)了一個(gè) 但是notifyall 將所有的進(jìn)程都解開(kāi)了 。。那兩個(gè)生產(chǎn)者進(jìn)程就會(huì)直接運(yùn)行if后面的東西并沒(méi)有被拉回來(lái)重新判斷一下。這樣就造成了number的值變成2.同理number變成負(fù)數(shù)也是有可能的(兩個(gè)消費(fèi)者進(jìn)程先進(jìn)來(lái)都堵塞).
這個(gè)問(wèn)題絕對(duì)是干貨,在工作中絕對(duì)會(huì)遇到生產(chǎn)者消費(fèi)者問(wèn)題,不少程序員會(huì)在這個(gè)地方踩坑。面試的時(shí)候如果考到你這個(gè)地方,你能解答出深層原理來(lái)。相信面試官會(huì)高看你一眼。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Java多線程通信wait()和notify()代碼實(shí)例
- Object類(lèi)wait及notify方法原理實(shí)例解析
- Java object wait notify notifyAll代碼解析
- Java多線程中的wait/notify通信模式實(shí)例詳解
- 分析java并發(fā)中的wait notify notifyAll
- java wait()/notify() 實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式詳解
- 基于線程的wait和notify使用,生產(chǎn)消費(fèi)案例
- Java如何正確的使用wait-notify方法你知道嗎
- 為什么wait和notify必須放在synchronized中使用
相關(guān)文章
使用Spring AOP監(jiān)控指定方法執(zhí)行時(shí)間的代碼詳解
這篇文章主要介紹了使用Spring AOP監(jiān)控指定方法執(zhí)行時(shí)間,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-08-08
Java設(shè)計(jì)模式中橋接模式應(yīng)用詳解
橋接,顧名思義,就是用來(lái)連接兩個(gè)部分,使得兩個(gè)部分可以互相通訊。橋接模式將系統(tǒng)的抽象部分與實(shí)現(xiàn)部分分離解耦,使他們可以獨(dú)立的變化。本文通過(guò)示例詳細(xì)介紹了橋接模式的原理與使用,需要的可以參考一下2022-11-11
詳解Spring Cloud Alibaba Sidecar多語(yǔ)言微服務(wù)異構(gòu)
這篇文章主要介紹了詳解Spring Cloud Alibaba Sidecar多語(yǔ)言微服務(wù)異構(gòu),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
Java實(shí)現(xiàn)的讀取資源文件工具類(lèi)ResourcesUtil實(shí)例【可動(dòng)態(tài)更改值的內(nèi)容】
這篇文章主要介紹了Java實(shí)現(xiàn)的讀取資源文件工具類(lèi)ResourcesUtil,結(jié)合實(shí)例形式分析了java針對(duì)資源文件的讀取與修改相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
Spring Boot基礎(chǔ)入門(mén)之基于注解的Mybatis
這篇文章主要給大家介紹了關(guān)于Spring Boot基礎(chǔ)入門(mén)之基于注解的Mybatis的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
淺談Java并發(fā) J.U.C之AQS:CLH同步隊(duì)列
AQS內(nèi)部維護(hù)著一個(gè)FIFO隊(duì)列,該隊(duì)列就是CLH同步隊(duì)列。下面小編來(lái)簡(jiǎn)單介紹下這個(gè)隊(duì)列2019-05-05

