色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

圖解Java多線程中的wait()和notify()方法

Android編程精選 ? 來(lái)源:CSDN-Killing Vibe ? 2023-03-22 09:29 ? 次閱讀

一、線程間等待與喚醒機(jī)制

wait()和notify()是Object類的方法,用于線程的等待與喚醒,必須搭配synchronized 鎖來(lái)使用。

多線程并發(fā)的場(chǎng)景下,有時(shí)需要某些線程先執(zhí)行,這些線程執(zhí)行結(jié)束后其他線程再繼續(xù)執(zhí)行。

比如: 一個(gè)長(zhǎng)跑比賽,裁判員要等跑步運(yùn)動(dòng)員沖線了才能宣判比賽結(jié)束,那裁判員線程就得等待所有的運(yùn)動(dòng)員線程運(yùn)行結(jié)束后,再喚醒這個(gè)裁判線程。

二、等待方法wait()

wait 做的事情:

使當(dāng)前執(zhí)行代碼的線程進(jìn)行等待. (把線程放到等待隊(duì)列中)

釋放當(dāng)前的鎖

滿足一定條件時(shí)被喚醒, 重新嘗試獲取這個(gè)鎖.

wait 要搭配 synchronized 來(lái)使用. 脫離 synchronized 使用 wait 會(huì)直接拋出異常.

887454d4-c7dc-11ed-bfe3-dac502259ad0.png

wait 結(jié)束等待的條件:

其他線程調(diào)用該對(duì)象的 notify 方法.

wait 等待時(shí)間超時(shí) (wait 方法提供一個(gè)帶有 timeout 參數(shù)的版本, 來(lái)指定等待時(shí)間).

其他線程調(diào)用該等待線程的 interrupted 方法, 導(dǎo)致 wait 拋出 InterruptedException 異常.

注意事項(xiàng):

調(diào)用wait()方法的前提是首先要獲取該對(duì)象的鎖(synchronize對(duì)象鎖)

調(diào)用wait()方法會(huì)釋放鎖,本線程進(jìn)入等待隊(duì)列等待被喚醒,被喚醒后不是立即恢復(fù)執(zhí)行,而是進(jìn)入阻塞隊(duì)列,競(jìng)爭(zhēng)鎖

等待方法:

1.癡漢方法,死等,線程進(jìn)入阻塞態(tài)(WAITING)直到有其他線程調(diào)用notify方法喚醒

88996dc8-c7dc-11ed-bfe3-dac502259ad0.png

2.等待一段時(shí)間,若在該時(shí)間內(nèi)線程被喚醒,則繼續(xù)執(zhí)行,若超過(guò)相應(yīng)時(shí)間還沒(méi)有其他線程喚醒此線程,此線程不再等待,恢復(fù)執(zhí)行。

88ab614a-c7dc-11ed-bfe3-dac502259ad0.png

調(diào)用wait方法之后:

88d99f06-c7dc-11ed-bfe3-dac502259ad0.png

三、喚醒方法notify()

notify 方法是喚醒等待的線程.

方法notify()也要在同步方法或同步塊中調(diào)用,該方法是用來(lái)通知那些可能等待該對(duì)象的對(duì)象鎖的其它線程,對(duì)其發(fā)出通知notify,并使它們重新獲取該對(duì)象的對(duì)象鎖。

如果有多個(gè)線程等待,則有線程調(diào)度器隨機(jī)挑選出一個(gè)呈 wait 狀態(tài)的線程。(并沒(méi)有 “先來(lái)后到”)

在notify()方法后,當(dāng)前線程不會(huì)馬上釋放該對(duì)象鎖,要等到執(zhí)行notify()方法的線程將程序執(zhí)行完,也就是退出同步代碼塊之后才會(huì)釋放對(duì)象鎖。

注意事項(xiàng):

notify():隨機(jī)喚醒一個(gè)處在等待狀態(tài)的線程。

notifyAll():喚醒所有處在等待狀態(tài)的線程。

無(wú)論是wait還是notify方法,都需要搭配synchronized鎖來(lái)使用(等待和喚醒,也是需要對(duì)象)

89317672-c7dc-11ed-bfe3-dac502259ad0.png

四、關(guān)于wait和notify內(nèi)部等待問(wèn)題(重要)

對(duì)于wait和notify方法,其實(shí)有一個(gè)阻塞隊(duì)列也有一個(gè)等待隊(duì)列。

阻塞隊(duì)列表示同一時(shí)間只有一個(gè)線程能獲取到鎖,其他線程進(jìn)入阻塞隊(duì)列

等待隊(duì)列表示調(diào)用wait (首先此線程要獲取到鎖,進(jìn)入等待隊(duì)列,釋放鎖)

舉個(gè)栗子:

現(xiàn)有如下定義的等待線程任務(wù)

privatestaticclassWaitTaskimplementsRunnable{
privateObjectlock;
publicWaitTask(Objectlock){
this.lock=lock;
}
@Override
publicvoidrun(){
synchronized(lock){
System.out.println(Thread.currentThread().getName()+"準(zhǔn)備進(jìn)入等待狀態(tài)");
//此線程在等待lock對(duì)象的notify方法喚醒
try{
lock.wait();
Thread.sleep(1000);
}catch(InterruptedExceptione){
thrownewRuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+"等待結(jié)束,本線程繼續(xù)執(zhí)行");
}
}
}

然后創(chuàng)建三個(gè)等待線程:

8961dd4e-c7dc-11ed-bfe3-dac502259ad0.png

由于同一時(shí)間只有一個(gè)線程(隨機(jī)調(diào)度)能獲取到synchronized鎖,所以會(huì)有兩個(gè)線程沒(méi)競(jìng)爭(zhēng)到鎖,從而進(jìn)入了阻塞隊(duì)列。

這里假如t2先競(jìng)爭(zhēng)到了鎖,所以先會(huì)阻塞t1和t3:

89af03bc-c7dc-11ed-bfe3-dac502259ad0.png

又由于調(diào)用wait方法會(huì)釋放鎖,調(diào)用wait方法的線程t2就會(huì)進(jìn)入等待隊(duì)列,直到被notify喚醒或者超時(shí)自動(dòng)喚醒。

89c6f49a-c7dc-11ed-bfe3-dac502259ad0.png

然后此時(shí)lock對(duì)象已經(jīng)被釋放了,所以t1和t3 又可以去競(jìng)爭(zhēng)這個(gè)鎖了,就從阻塞隊(duì)列里面競(jìng)爭(zhēng)鎖。

這里假如t3 競(jìng)爭(zhēng)到了鎖,阻塞隊(duì)列只剩下t1:

89da9c7a-c7dc-11ed-bfe3-dac502259ad0.png

然后t3運(yùn)行到了wait方法,釋放鎖,然后進(jìn)入等待隊(duì)列:

89f51a96-c7dc-11ed-bfe3-dac502259ad0.png

然后重復(fù)這些操作~~,最后t1,t2,t3 都進(jìn)入了等待隊(duì)列中,等待notify線程喚醒(這里假設(shè)notify要放在這些線程start后的好幾秒后,因?yàn)閚otify線程也是和這些線程并發(fā)執(zhí)行的,所以等待隊(duì)列中的線程隨時(shí)可能被喚醒)

8a103be6-c7dc-11ed-bfe3-dac502259ad0.png

重點(diǎn)來(lái)了:

在等待隊(duì)列中的線程,被notify喚醒之后,會(huì)直接回到阻塞隊(duì)列去競(jìng)爭(zhēng)鎖!!!而不是直接喚醒~

舉個(gè)栗子:

拿notifyAll()來(lái)舉例,假如此時(shí)等待隊(duì)列中有三個(gè)線程t1,t2,t3,那么調(diào)用notifyAll()會(huì)直接把它們?nèi)齻€(gè)直接從等待隊(duì)列中進(jìn)入到阻塞隊(duì)列中:

8a28df34-c7dc-11ed-bfe3-dac502259ad0.png

然后再去競(jìng)爭(zhēng)這個(gè)鎖,去執(zhí)行wait之后的代碼~~

五、完整代碼(僅供測(cè)試用)

privatestaticclassWaitTaskimplementsRunnable{
privateObjectlock;
publicWaitTask(Objectlock){
this.lock=lock;
}
@Override
publicvoidrun(){
synchronized(lock){
System.out.println(Thread.currentThread().getName()+"準(zhǔn)備進(jìn)入等待狀態(tài)");
//此線程在等待lock對(duì)象的notify方法喚醒
try{
lock.wait();
Thread.sleep(1000);
}catch(InterruptedExceptione){
thrownewRuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+"等待結(jié)束,本線程繼續(xù)執(zhí)行");
}
}
}
privatestaticclassNotifyTaskimplementsRunnable{
privateObjectlock;
publicNotifyTask(Objectlock){
this.lock=lock;
}
@Override
publicvoidrun(){
synchronized(lock){
System.out.println("準(zhǔn)備喚醒");
//喚醒所有線程(隨機(jī))
lock.notifyAll();
System.out.println("喚醒結(jié)束");
}
}
}

publicstaticvoidmain(String[]args)throwsInterruptedException{
Objectlock=newObject();
Objectlock2=newObject();
//創(chuàng)建三個(gè)等待線程
Threadt1=newThread(newWaitTask(lock),"t1");
Threadt2=newThread(newWaitTask(lock),"t2");
Threadt3=newThread(newWaitTask(lock),"t3");
//創(chuàng)建一個(gè)喚醒線程
Threadnotify=newThread(newNotifyTask(lock2),"notify線程");
t1.start();
t2.start();
t3.start();
;
Thread.sleep(100);
notify.start();
//當(dāng)前正在執(zhí)行的線程數(shù)
Thread.sleep(2000);
System.out.println(Thread.activeCount()-1);
}

六、wait和sleep方法的區(qū)別(面試題):

wait方法是Object類提供的方法,需要搭配synchronized鎖來(lái)使用,調(diào)用wait方法會(huì)釋放鎖,線程進(jìn)入WAITING狀態(tài),等待被其他線程喚醒或者超時(shí)自動(dòng)喚醒,喚醒之后的線程需要再次競(jìng)爭(zhēng)synchronized鎖才能繼續(xù)執(zhí)行。

sleep方法是Thread類提供的方法,調(diào)用sleep方法的線程進(jìn)入TIMED_WAITING狀態(tài),不會(huì)釋放鎖,時(shí)間到自動(dòng)喚醒。

總結(jié)

以上就是多線程場(chǎng)景下wait和notify方法的詳解和注意事項(xiàng)了,碼字不易,有幫助的話別忘了關(guān)注,點(diǎn)贊+收藏哦~

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2966

    瀏覽量

    104704
  • 多線程
    +關(guān)注

    關(guān)注

    0

    文章

    278

    瀏覽量

    19946
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4780

    瀏覽量

    68529
  • 線程
    +關(guān)注

    關(guān)注

    0

    文章

    504

    瀏覽量

    19675
  • WAIT
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    2512

原文標(biāo)題:圖解 Java多線程中的 wait() 和 notify() 方法

文章出處:【微信號(hào):AndroidPush,微信公眾號(hào):Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Java多線程的用法

    本文將介紹一下Java多線程的用法。 基礎(chǔ)介紹 什么是多線程 指的是在一個(gè)進(jìn)程同時(shí)運(yùn)行多個(gè)線程,每個(gè)
    的頭像 發(fā)表于 09-30 17:07 ?947次閱讀

    Javasleep和wait的區(qū)別

    sleep()、suspend()、resume()方法不推薦使用,推薦使用wait()、notify()、notifyAll()。  sleep()方法是使
    發(fā)表于 11-25 11:50

    Java線程阻塞方法大全

    ()方法,當(dāng)前線程轉(zhuǎn)A入阻塞狀態(tài),直到線程B運(yùn)行結(jié)束,線程A才由阻塞狀態(tài)轉(zhuǎn)為可執(zhí)行狀態(tài)。以上是Java
    發(fā)表于 04-02 15:42

    Java線程喚醒與阻塞規(guī)則

    的join()方法,當(dāng)前線程轉(zhuǎn)A入阻塞狀態(tài),直到線程B運(yùn)行結(jié)束,線程A才由阻塞狀態(tài)轉(zhuǎn)為可執(zhí)行狀態(tài)。以上是Java
    發(fā)表于 07-06 15:11

    java】?jī)煞N方式實(shí)現(xiàn)線程通信:三個(gè)線程交替打印AABBCC

    ()、signal()方法。使用wait/notify進(jìn)行線程通信只能夠隨機(jī)喚醒,增加了上下文的切換時(shí)間,使用await/signal可以實(shí)現(xiàn)精準(zhǔn)喚醒,
    發(fā)表于 09-20 16:38

    Java基礎(chǔ)學(xué)習(xí)多線程使用指南

    黑馬程序員-----Java基礎(chǔ)學(xué)習(xí)多線程
    發(fā)表于 10-08 14:10

    java多線程編程實(shí)例 (源程序)

    java多線程編程實(shí)例 import java.awt.*;import javax.swing.*; public class CompMover extends Object { 
    發(fā)表于 10-22 11:48 ?0次下載

    java多線程設(shè)計(jì)模式_結(jié)城浩

    JAVA多線程設(shè)計(jì)模式》通過(guò)淺顯易懂的文字與實(shí)例來(lái)介紹JAVA線程相關(guān)的設(shè)計(jì)模式概念,并且通過(guò)實(shí)際的JAVA程序范例和UML圖示來(lái)一一解說(shuō)
    發(fā)表于 01-05 16:15 ?0次下載
    <b class='flag-5'>java</b><b class='flag-5'>多線程</b>設(shè)計(jì)模式_結(jié)城浩

    java多線程同步方法

    二、為什么要線程同步 因?yàn)楫?dāng)我們有多個(gè)線程要同時(shí)訪問(wèn)一個(gè)變量或?qū)ο髸r(shí),如果這些線程既有讀又有寫操作時(shí),就會(huì)導(dǎo)致變量值或?qū)ο蟮臓顟B(tài)出現(xiàn)混亂,從而導(dǎo)致程序異常。舉個(gè)例子,如果一個(gè)銀行賬戶
    發(fā)表于 09-27 13:19 ?0次下載

    分析在javasleep和wait的不同

    的監(jiān)控狀態(tài)依然保持者,當(dāng)指定的時(shí)間到了又會(huì)自動(dòng)恢復(fù)運(yùn)行狀態(tài)。 在調(diào)用sleep()方法的過(guò)程線程不會(huì)釋放對(duì)象鎖。 而當(dāng)調(diào)用wait()方法
    發(fā)表于 09-27 14:41 ?0次下載

    Java多線程總結(jié)之Queue

    Java多線程應(yīng)用,隊(duì)列的使用率很高,多數(shù)生產(chǎn)消費(fèi)模型的首選數(shù)據(jù)結(jié)構(gòu)就是隊(duì)列。Java提供的線程安全的Queue可以分為 阻塞隊(duì)列和非阻
    發(fā)表于 11-28 16:14 ?3304次閱讀
    <b class='flag-5'>Java</b><b class='flag-5'>多線程</b>總結(jié)之Queue

    java學(xué)習(xí)——java面試【事務(wù)、鎖、多線程】資料整理

    本文檔內(nèi)容介紹了基于java學(xué)習(xí)java面試【事務(wù)、鎖、多線程】資料整理,供參考
    發(fā)表于 03-13 13:53 ?0次下載

    Java教程之零點(diǎn)起飛學(xué)Java線程資料說(shuō)明

    多線程編程是提高應(yīng)用程序性能的重要手段之一。Java平臺(tái)從開(kāi)始就被設(shè)計(jì)成為多線程環(huán)境,從語(yǔ)言級(jí)上支持多線程。在Java語(yǔ)言中,提供了創(chuàng)建、啟
    發(fā)表于 02-20 10:41 ?3次下載
    <b class='flag-5'>Java</b>教程之零點(diǎn)起飛學(xué)<b class='flag-5'>Java</b>的<b class='flag-5'>線程</b>資料說(shuō)明

    Java多線程永動(dòng)任務(wù) 多線程異步任務(wù)項(xiàng)目解讀

    1. 功能說(shuō)明 2. 多線程任務(wù)示例 2.1 線程池 2.2 單個(gè)任務(wù) 2.3 任務(wù)入口 2.4 結(jié)果分析 2.5 源碼地址 3. 寫在最后 大家好,今天教大家擼一個(gè) Java多線程
    的頭像 發(fā)表于 10-19 11:46 ?1118次閱讀

    java實(shí)現(xiàn)多線程的幾種方式

    Java實(shí)現(xiàn)多線程的幾種方式 多線程是指程序包含了兩個(gè)或以上的線程,每個(gè)線程都可以并行執(zhí)行不同
    的頭像 發(fā)表于 03-14 16:55 ?691次閱讀
    主站蜘蛛池模板: 国产美女裸身网站免费观看视频| 99re久久热在线播放快| 男人和女人一级黄色大片| 美女强奷到抽搐在线播放| 精品水蜜桃久久久久久久| 精品夜夜澡人妻无码AV蜜桃| 花蝴蝶在线直播观看| 精品水蜜桃久久久久久久| 久久精品国产亚洲AV妓女不卡| 成人AV无码一二二区视频免费看| 多男同时插一个女人8p| 全彩无翼污之邪恶女教师| 欧美亚洲国产手机在线有码| 欧洲精品不卡1卡2卡三卡四卡| 人妻久久久精品99系列AV| 日韩午夜影院| 亚洲AV无码专区国产精品99| 亚洲精品AV无码喷奶水糖心| 亚洲AV精品一区二区三区不卡| 日本阿v片在线播放免费| 亚洲激情网站| 99爱在线精品视频免费观看9| 国产高清视频a在线大全| 久久99国产亚洲高清观着| 全肉高H短篇合集| 亚洲精品成人无码区一在线观看| 在线亚洲色拍偷拍在线视频| 99久久爱re热6在线播放| 国产一级特黄a大片99| 扒开黑女人p大荫蒂老女人 | 漂亮妈妈中文字幕版| 小蝌蚪视频在线观看免费观看WWW| 在线观看国产视频| 国产成人久久婷婷精品流白浆| 啦啦啦影院视频在线看高清...| 欧洲内射XXX高清| 亚洲精品一区三区三区在线观看| CHESENGAY痞帅警察GV| 成人精品综合免费视频| 国产真实强被迫伦姧女在线观看| 浪货嗯啊趴下NP粗口黄暴|