線程中的sleep()和wait();

線程在一定條件下瞳腌,狀態(tài)會(huì)發(fā)生變化。線程一共有以下幾種狀態(tài):

1很泊、新建狀態(tài)(New):新創(chuàng)建了一個(gè)線程對(duì)象。

2沾谓、就緒狀態(tài)(Runnable):線程對(duì)象創(chuàng)建后委造,其他線程調(diào)用了該對(duì)象的start()方法。該狀態(tài)的線程位于“可運(yùn)行線程池”中均驶,變得可運(yùn)行昏兆,只等待獲取CPU的使用權(quán)即在就緒狀態(tài)的進(jìn)程除CPU之外辣恋,其它的運(yùn)行所需資源都已全部獲得亮垫。

3、運(yùn)行狀態(tài)(Running):就緒狀態(tài)的線程獲取了CPU伟骨,執(zhí)行程序代碼饮潦。

4、阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因?yàn)槟撤N原因放棄CPU使用權(quán)携狭,暫時(shí)停止運(yùn)行继蜡。直到線程進(jìn)入就緒狀態(tài),才有機(jī)會(huì)轉(zhuǎn)到運(yùn)行狀態(tài)逛腿。

阻塞的情況分三種:

(1)稀并、等待阻塞:運(yùn)行的線程執(zhí)行wait()方法,該線程會(huì)釋放占用的所有資源单默,JVM會(huì)把該線程放入“等待池”中碘举。進(jìn)入這個(gè)狀態(tài)后,是不能自動(dòng)喚醒的搁廓,必須依靠其他線程調(diào)用notify()或notifyAll()方法才能被喚醒引颈,

(2)、同步阻塞:運(yùn)行的線程在獲取對(duì)象的同步鎖時(shí)境蜕,若該同步鎖被別的線程占用蝙场,則JVM會(huì)把該線程放入“鎖池”中。

(3)粱年、其他阻塞:運(yùn)行的線程執(zhí)行sleep()或join()方法售滤,或者發(fā)出了I/O請(qǐng)求時(shí),JVM會(huì)把該線程置為阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時(shí)完箩、join()等待線程終止或者超時(shí)赐俗、或者I/O處理完畢時(shí),線程重新轉(zhuǎn)入就緒狀態(tài)嗜憔。

5秃励、死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法,該線程結(jié)束生命周期吉捶。

線程變化的狀態(tài)轉(zhuǎn)換圖如下:


注:拿到對(duì)象的鎖標(biāo)記

夺鲜,即為獲得了對(duì)該對(duì)象(

臨界區(qū)

)的使用權(quán)限。即該線程獲得了運(yùn)行所需的資源呐舔,進(jìn)入“就緒狀態(tài)”币励,只需獲得CPU,就可以運(yùn)行珊拼。因?yàn)?/p>

當(dāng)調(diào)用wait()后食呻,線程會(huì)釋放掉它所占有的“鎖標(biāo)志”,所以線程只有在此獲取資源才能進(jìn)入就緒狀態(tài)澎现。

下面小小的作下解釋:

1仅胞、線程的實(shí)現(xiàn)有兩種方式,一是繼承Thread類剑辫,二是實(shí)現(xiàn)Runnable接口干旧,但不管怎樣,??當(dāng)我們new了這個(gè)對(duì)象后妹蔽,線程就進(jìn)入了初始狀態(tài)椎眯;

2、當(dāng)該對(duì)象調(diào)用了start()方法胳岂,就進(jìn)入就緒狀態(tài)编整;

3、進(jìn)入就緒后乳丰,當(dāng)該對(duì)象被操作系統(tǒng)選中掌测,獲得CPU時(shí)間片就會(huì)進(jìn)入運(yùn)行狀態(tài);

4产园、進(jìn)入運(yùn)行狀態(tài)后情況就比較復(fù)雜了

4.1汞斧、run()方法或main()方法結(jié)束后,線程就進(jìn)入終止?fàn)顟B(tài)淆两;

4.2断箫、當(dāng)線程調(diào)用了自身的sleep()方法或其他線程的join()方法拂酣,進(jìn)程讓出CPU秋冰,然后就會(huì)進(jìn)入阻塞狀態(tài)(該狀態(tài)既停止當(dāng)前線程,但并不釋放所占有的資源即調(diào)用sleep ()函數(shù)后婶熬,線程不會(huì)釋放它的“鎖標(biāo)志”剑勾。)埃撵。當(dāng)sleep()結(jié)束或join()結(jié)束后,該線程進(jìn)入可運(yùn)行狀態(tài)虽另,繼續(xù)等待OS分配CPU時(shí)間片暂刘。典型地,sleep()被用在等待某個(gè)資源就緒的情形:測(cè)試發(fā)現(xiàn)條件不滿足后捂刺,讓線程阻塞一段時(shí)間后重新測(cè)試谣拣,直到條件滿足為止。

4.3族展、線程調(diào)用了yield()方法森缠,意思是放棄當(dāng)前獲得的CPU時(shí)間片,回到就緒狀態(tài)仪缸,這時(shí)與其他進(jìn)程處于同等競(jìng)爭(zhēng)狀態(tài)贵涵,OS有可能會(huì)接著又讓這個(gè)進(jìn)程進(jìn)入運(yùn)行狀態(tài);?調(diào)用?yield()?的效果等價(jià)于調(diào)度程序認(rèn)為該線程已執(zhí)行了足夠的時(shí)間片從而需要轉(zhuǎn)到另一個(gè)線程恰画。yield()只是使當(dāng)前線程重新回到可執(zhí)行狀態(tài)宾茂,所以執(zhí)行yield()的線程有可能在進(jìn)入到可執(zhí)行狀態(tài)后馬上又被執(zhí)行。

4.4拴还、當(dāng)線程剛進(jìn)入可運(yùn)行狀態(tài)(注意跨晴,還沒(méi)運(yùn)行),發(fā)現(xiàn)將要調(diào)用的資源被synchroniza(同步)自沧,獲取不到鎖標(biāo)記坟奥,將會(huì)立即進(jìn)入鎖池狀態(tài),等待獲取鎖標(biāo)記(這時(shí)的鎖池里也許已經(jīng)有了其他線程在等待獲取鎖標(biāo)記拇厢,這時(shí)它們處于隊(duì)列狀態(tài)爱谁,既先到先得),一旦線程獲得鎖標(biāo)記后孝偎,就轉(zhuǎn)入就緒狀態(tài)访敌,等待OS分配CPU時(shí)間片;

4.5.suspend()和?resume()方法:兩個(gè)方法配套使用衣盾,suspend()使得線程進(jìn)入阻塞狀態(tài)寺旺,并且不會(huì)自動(dòng)恢復(fù),必須其對(duì)應(yīng)的resume()被調(diào)用势决,才能使得線程重新進(jìn)入可執(zhí)行狀態(tài)阻塑。典型地,suspend()和?resume()?被用在等待另一個(gè)線程產(chǎn)生的結(jié)果的情形:測(cè)試發(fā)現(xiàn)結(jié)果還沒(méi)有產(chǎn)生后果复,讓線程阻塞陈莽,另一個(gè)線程產(chǎn)生了結(jié)果后,調(diào)用?resume()使其恢復(fù)。

4.6走搁、wait()和?notify()?方法:當(dāng)線程調(diào)用wait()方法后會(huì)進(jìn)入等待隊(duì)列(進(jìn)入這個(gè)狀態(tài)會(huì)釋放所占有的所有資源独柑,與阻塞狀態(tài)不同),進(jìn)入這個(gè)狀態(tài)后私植,是不能自動(dòng)喚醒的忌栅,必須依靠其他線程調(diào)用notify()或notifyAll()方法才能被喚醒(由于notify()只是喚醒一個(gè)線程,但我們由不能確定具體喚醒的是哪一個(gè)線程曲稼,也許我們需要喚醒的線程不能夠被喚醒索绪,因此在實(shí)際使用時(shí),一般都用notifyAll()方法贫悄,喚醒有所線程)者春,線程被喚醒后會(huì)進(jìn)入鎖池,等待獲取鎖標(biāo)記清女。

wait()?使得線程進(jìn)入阻塞狀態(tài)钱烟,它有兩種形式:

一種允許指定以毫秒為單位的一段時(shí)間作為參數(shù);另一種沒(méi)有參數(shù)嫡丙。前者當(dāng)對(duì)應(yīng)的?notify()被調(diào)用或者超出指定時(shí)間時(shí)線程重新進(jìn)入可執(zhí)行狀態(tài)即就緒狀態(tài)拴袭,后者則必須對(duì)應(yīng)的?notify()被調(diào)用。當(dāng)調(diào)用wait()后曙博,線程會(huì)釋放掉它所占有的“鎖標(biāo)志”拥刻,從而使線程所在對(duì)象中的其它synchronized數(shù)據(jù)可被別的線程使用。waite()和notify()因?yàn)闀?huì)對(duì)對(duì)象的“鎖標(biāo)志”進(jìn)行操作父泳,所以它們必須在synchronized函數(shù)或synchronizedblock中進(jìn)行調(diào)用般哼。如果在non-synchronized函數(shù)或non-synchronizedblock中進(jìn)行調(diào)用,雖然能編譯通過(guò)惠窄,但在運(yùn)行時(shí)會(huì)發(fā)生IllegalMonitorStateException的異常蒸眠。

注意區(qū)別:初看起來(lái)wait()?和?notify()?方法與suspend()和?resume()?方法對(duì)沒(méi)有什么分別,但是事實(shí)上它們是截然不同的杆融。區(qū)別的核心在于楞卡,前面敘述的suspend()及其它所有方法在線程阻塞時(shí)都不會(huì)釋放占用的鎖(如果占用了的話),而wait()?和?notify()?這一對(duì)方法則相反脾歇。

上述的核心區(qū)別導(dǎo)致了一系列的細(xì)節(jié)上的區(qū)別

首先蒋腮,前面敘述的所有方法都隸屬于?Thread類,但是wait()?和?notify()?方法這一對(duì)卻直接隸屬于?Object?類藕各,也就是說(shuō)池摧,所有對(duì)象都擁有這一對(duì)方法。初看起來(lái)這十分不可思議激况,但是實(shí)際上卻是很自然的作彤,因?yàn)檫@一對(duì)方法阻塞時(shí)要釋放占用的鎖踢京,而鎖是任何對(duì)象都具有的,調(diào)用任意對(duì)象的?wait()?方法導(dǎo)致線程阻塞宦棺,并且該對(duì)象上的鎖被釋放。而調(diào)用任意對(duì)象的notify()方法則導(dǎo)致因調(diào)用該對(duì)象的?wait()方法而阻塞的線程中隨機(jī)選擇的一個(gè)解除阻塞(但要等到獲得鎖后才真正可執(zhí)行)黔帕。

其次代咸,前面敘述的所有方法都可在任何位置調(diào)用,但是wait()?和?notify()?方法這一對(duì)方法卻必須在?synchronized?方法或塊中調(diào)用成黄,理由也很簡(jiǎn)單呐芥,只有在synchronized方法或塊中當(dāng)前線程才占有鎖,才有鎖可以釋放奋岁。同樣的道理思瘟,調(diào)用這一對(duì)方法的對(duì)象上的鎖必須為當(dāng)前線程所擁有,這樣才有鎖可以釋放闻伶。因此滨攻,這一對(duì)方法調(diào)用必須放置在這樣的?synchronized方法或塊中,該方法或塊的上鎖對(duì)象就是調(diào)用這一對(duì)方法的對(duì)象蓝翰。若不滿足這一條件光绕,則程序雖然仍能編譯,但在運(yùn)行時(shí)會(huì)出現(xiàn)IllegalMonitorStateException異常畜份。

wait()?和?notify()方法的上述特性決定了它們經(jīng)常和synchronized方法或塊一起使用诞帐,將它們和操作系統(tǒng)的進(jìn)程間通信機(jī)制作一個(gè)比較就會(huì)發(fā)現(xiàn)它們的相似性:synchronized方法或塊提供了類似于操作系統(tǒng)原語(yǔ)的功能,它們的執(zhí)行不會(huì)受到多線程機(jī)制的干擾爆雹,而這一對(duì)方法則相當(dāng)于?block和wake up?原語(yǔ)(這一對(duì)方法均聲明為?synchronized)停蕉。它們的結(jié)合使得我們可以實(shí)現(xiàn)操作系統(tǒng)上一系列精妙的進(jìn)程間通信的算法(如信號(hào)量算法),并用于解決各種復(fù)雜的線程間通信問(wèn)題钙态。

關(guān)于?wait()?和?notify()?方法最后再說(shuō)明兩點(diǎn):

第一:調(diào)用notify()?方法導(dǎo)致解除阻塞的線程是從因調(diào)用該對(duì)象的?wait()方法而阻塞的線程中隨機(jī)選取的慧起,我們無(wú)法預(yù)料哪一個(gè)線程將會(huì)被選擇,所以編程時(shí)要特別小心册倒,避免因這種不確定性而產(chǎn)生問(wèn)題完慧。

第二:除了notify(),還有一個(gè)方法?notifyAll()也可起到類似作用剩失,唯一的區(qū)別在于屈尼,調(diào)用?notifyAll()方法將把因調(diào)用該對(duì)象的?wait()方法而阻塞的所有線程一次性全部解除阻塞。當(dāng)然拴孤,只有獲得鎖的那一個(gè)線程才能進(jìn)入可執(zhí)行狀態(tài)脾歧。

談到阻塞,就不能不談一談死鎖演熟,略一分析就能發(fā)現(xiàn)鞭执,suspend()方法和不指定超時(shí)期限的wait()方法的調(diào)用都可能產(chǎn)生死鎖司顿。遺憾的是,Java并不在語(yǔ)言級(jí)別上支持死鎖的避免兄纺,我們?cè)诰幊讨斜仨毿⌒牡乇苊馑梨i大溜。

官方JAVA8的API解釋:

sleep()

public static void sleep(long millis) ?throwsInterruptedException

Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.

wait()

public final void wait(long timeout) throwsInterruptedException

Causes the current thread to wait until either another thread invokes thenotify()method or thenotifyAll()method for this object, or a specified amount of time has elapsed.

The current thread must own this object's monitor.

博客來(lái)自http://www.cnblogs.com/jijijiefang/articles/7222955.html;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末估脆,一起剝皮案震驚了整個(gè)濱河市钦奋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疙赠,老刑警劉巖付材,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異圃阳,居然都是意外死亡厌衔,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門捍岳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)富寿,“玉大人,你說(shuō)我怎么就攤上這事锣夹∽鞔” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵晕城,是天一觀的道長(zhǎng)泞坦。 經(jīng)常有香客問(wèn)我,道長(zhǎng)砖顷,這世上最難降的妖魔是什么贰锁? 我笑而不...
    開(kāi)封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮滤蝠,結(jié)果婚禮上豌熄,老公的妹妹穿的比我還像新娘。我一直安慰自己物咳,他們只是感情好锣险,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著览闰,像睡著了一般芯肤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上压鉴,一...
    開(kāi)封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天崖咨,我揣著相機(jī)與錄音,去河邊找鬼油吭。 笑死击蹲,一個(gè)胖子當(dāng)著我的面吹牛署拟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播歌豺,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼推穷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了类咧?” 一聲冷哼從身側(cè)響起馒铃,我...
    開(kāi)封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎轮听,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體岭佳,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡血巍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了珊随。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片述寡。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖叶洞,靈堂內(nèi)的尸體忽然破棺而出鲫凶,到底是詐尸還是另有隱情,我是刑警寧澤衩辟,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布螟炫,位于F島的核電站,受9級(jí)特大地震影響艺晴,放射性物質(zhì)發(fā)生泄漏昼钻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一封寞、第九天 我趴在偏房一處隱蔽的房頂上張望然评。 院中可真熱鬧,春花似錦狈究、人聲如沸碗淌。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)亿眠。三九已至,卻和暖如春磅废,著一層夾襖步出監(jiān)牢的瞬間缕探,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工还蹲, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留爹耗,地道東北人耙考。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像潭兽,于是被迫代替她去往敵國(guó)和親倦始。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 1.解決信號(hào)量丟失和假喚醒 public class MyWaitNotify3{ MonitorObject m...
    Q羅閱讀 871評(píng)論 0 1
  • 相關(guān)概念 面向?qū)ο蟮娜齻€(gè)特征 封裝,繼承,多態(tài).這個(gè)應(yīng)該是人人皆知.有時(shí)候也會(huì)加上抽象. 多態(tài)的好處 允許不同類對(duì)...
    東經(jīng)315度閱讀 1,925評(píng)論 0 8
  • 根據(jù)一些資料整理如下:一個(gè)程序中可以有多條執(zhí)行線索同時(shí)執(zhí)行山卦,一個(gè)線程就是程序中的一條執(zhí)行線索鞋邑,每個(gè)線程上都關(guān)聯(lián)有要...
    herenoone閱讀 488評(píng)論 0 0
  • 一、安裝SercureCRT 1账蓉、安裝包鏈接:http://pan.baidu.com/s/1qXHChIG 密碼...
    海豚的小小海閱讀 2,648評(píng)論 0 0
  • 二年級(jí)寒假枚碗,爸爸送我一只兩個(gè)月大的小狗我們給它取名叫豆豆。它的毛茸茸的铸本,渾身淺黃肮雨,鼻子黑黑的,它舔了一下鼻子...
    毛毛蟲(chóng)爬呀爬閱讀 270評(píng)論 0 0