JAVA學(xué)習(xí)筆記--線程狀態(tài)及對(duì)象鎖
https://my.oschina.net/goldenshaw/blog?catalog=3277710&temp=1499785479453
[TOC]
一、線程狀態(tài)
-
【NEW】 新建尚未運(yùn)行
還沒調(diào)用start童漩,或者調(diào)用了start()方法沸久,不一定立即改變線程狀態(tài),中間可能需要一些步驟才完成一個(gè)線程的啟動(dòng)
-
【RUNNABLE】 處于可運(yùn)行狀態(tài):正在運(yùn)行或準(zhǔn)備運(yùn)行
start調(diào)用結(jié)束扮碧,線程由NEW變成RUNNABLE,存活著并嘗試占用CPU資源,yield操作,線程還是RUNNABLE狀態(tài)豁生,只是他有一個(gè)細(xì)節(jié)的內(nèi)部變化酸纲,做一個(gè)簡(jiǎn)單的讓步捣鲸。在JAVA層面是RUNNABLE的狀態(tài),并不代表一定處于運(yùn)行中的狀態(tài)闽坡,比例BIO中栽惶,線程正阻塞在網(wǎng)絡(luò)等待的時(shí)候愁溜,看到的狀態(tài)依然是RUNNABLE狀態(tài),而底層線程已經(jīng)被阻塞了外厂。
-
【BLOCKED】 等待獲取鎖時(shí)進(jìn)入的狀態(tài)
線程被掛起了冕象,通常是因?yàn)樗诘却粋€(gè)鎖,當(dāng)synchronized正好有線程在使用時(shí)汁蝶,另外一個(gè)線程嘗試進(jìn)入這個(gè)臨界區(qū)就會(huì)被阻塞渐扮,直到另一個(gè)線程走完臨界區(qū),或者發(fā)生響應(yīng)鎖對(duì)象的wait操作掖棉,他才有機(jī)會(huì)去爭(zhēng)奪臨界區(qū)的權(quán)利墓律。搶到鎖之后,狀態(tài)從阻塞轉(zhuǎn)到RUNNABLE
線程等待IO操作會(huì)進(jìn)入BLOCKED狀態(tài) -
【W(wǎng)AITING】 通過wait方法進(jìn)入的等待
當(dāng)wart/join/park方法調(diào)用后幔亥,無限期地等待另一個(gè)線程來執(zhí)行某一特定操作的線程處于WAITING狀態(tài)耻讽。
-
【TIMED_WAITING】 等待另一個(gè)線程來執(zhí)行取決于指定等待時(shí)間的操作的線程處于這種狀態(tài)。
通過wait(t),sleep(t),join(t),parkNanos,parkUntil等方法進(jìn)入此狀態(tài)帕棉。當(dāng)時(shí)間達(dá)到時(shí)觸發(fā)線程回到工作狀態(tài)Runnable针肥。
interrupt只對(duì)處于waiting或timed_waiting狀態(tài)的線程起作用,對(duì)其他狀態(tài)不起作用香伴。 -
【TERMINATED】 已退出的線程處于這種狀態(tài)慰枕。
線程結(jié)束了,就處于這種狀態(tài)瞒窒,也就是run方法運(yùn)行完了捺僻。在操作系統(tǒng)內(nèi)部可能已經(jīng)注銷了相應(yīng)的線程,或者將它復(fù)用給其他需要使用線程的請(qǐng)求崇裁。
New->Runnable: start()
Runnable->Blocked: lock
Blocked-->Runnable: unLock
Runnable->Waiting: wait()/sleep()/join()/IO
Waiting-->Runnable: wait匕坯、sleep、join結(jié)束/IO結(jié)束
Runnable->Timed_waiting: wait(T)/sleep(T)/join(T)
Timed_waiting-->Runnable: wait拔稳、sleep葛峻、join時(shí)間到
Runnable->Terminated: 正常退出/異常
BLOCKED和WAITING狀態(tài)區(qū)別:
A、blocked是虛擬機(jī)認(rèn)為程序還不能進(jìn)入某個(gè)區(qū)域巴比,因?yàn)橥瑫r(shí)進(jìn)去就會(huì)有問題术奖,這是一塊臨界區(qū)。
B轻绞、發(fā)生wait等操作的先決條件是要進(jìn)入臨界區(qū)采记,也就是線程已經(jīng)拿到鎖了,自己可能進(jìn)去做了一些事情政勃,但此時(shí)通過判定業(yè)務(wù)上的參數(shù)唧龄,發(fā)現(xiàn)還有一些其他配合的資源沒有準(zhǔn)備充分,那么自己就等等再做其他事情奸远。
在waiting狀態(tài)下既棺,如果發(fā)生了interrupt操作讽挟,則處于該狀態(tài)的線程在內(nèi)部會(huì)拋出一個(gè)InterruptedException【跑出異常后,線程還需要獲取到對(duì)應(yīng)鎖才能繼續(xù)執(zhí)行后續(xù)操作】丸冕,這個(gè)異常應(yīng)當(dāng)在run方法內(nèi)捕獲耽梅,使得run方法正常地執(zhí)行完成,當(dāng)然捕獲異常后胖烛,是決定讓線程繼續(xù)運(yùn)行眼姐,還是結(jié)束等要根據(jù)業(yè)務(wù)場(chǎng)景才處理。
IO操作會(huì)導(dǎo)致線程進(jìn)入WAITING狀態(tài) 參考 https://my.oschina.net/goldenshaw/blog/705397
二洪己、對(duì)象鎖
- 所有對(duì)象都自動(dòng)含有單一的鎖
- JVM負(fù)責(zé)跟蹤對(duì)象被加鎖的次數(shù)妥凳。第一個(gè)線程第一次獲取到對(duì)象鎖時(shí)候,鎖計(jì)數(shù)為1答捕,此線程再次獲取這個(gè)對(duì)象的鎖計(jì)數(shù)加一,釋放一次減一直到全部釋放(計(jì)數(shù)為0)其他線程才可以獲取此對(duì)象的鎖屑那。
- 只有首先獲得鎖的任務(wù)(線程)才能繼續(xù)獲取該對(duì)象上的多個(gè)鎖拱镐。
Object.wait()
線程必須先獲取到對(duì)象監(jiān)視鎖,才能調(diào)用此方法持际。執(zhí)行此方法線程立即釋放對(duì)象監(jiān)視鎖,當(dāng)前線程阻塞沃琅。若方法拋出InterruptedException異常,同樣需要獲取鎖才能繼續(xù)往下執(zhí)行
Object.notify()
線程必須先獲取到對(duì)象監(jiān)視鎖蜘欲,才能調(diào)用此方法益眉。執(zhí)行此方法會(huì)喚起wait的線程,當(dāng)前線程不會(huì)立即是否鎖姥份,直到臨界區(qū)代碼庫執(zhí)行完線程釋放鎖之后郭脂,其他線程才有機(jī)會(huì)去競(jìng)爭(zhēng)鎖。
Thread.sleep() //當(dāng)前線程阻塞澈歉,不釋放鎖
Thread.yield() //讓出CPU執(zhí)行時(shí)間展鸡,不釋放鎖