1.線程生命周期
2.按圖分析
當(dāng)線程通過new創(chuàng)建了一個(gè)Thread的時(shí)候,線程就處于New狀態(tài)。
1.當(dāng)這個(gè)Thread對(duì)象調(diào)用了start()方法的時(shí)候,這個(gè)線程就進(jìn)入到了Runable狀態(tài),也就是擁有了被執(zhí)行的資格,正在等待獲得CPU資源。
2.當(dāng)這個(gè)線程得到CPU資源,他就會(huì)進(jìn)入到Running狀態(tài),這時(shí)候會(huì)執(zhí)行Thread里的run()方法的任務(wù)。
3.當(dāng)這個(gè)線程執(zhí)行完run()方法的任務(wù)或者執(zhí)行過程中出現(xiàn)異常,那么線程就會(huì)進(jìn)入到Dead狀態(tài)。
4.當(dāng)這個(gè)線程調(diào)用了yield()的方法的時(shí)候,該線程就會(huì)進(jìn)入到Runnable狀態(tài)。繼續(xù)等待獲得CPU資源。
5.當(dāng)這個(gè)線程調(diào)用了sleep()或者I/O阻塞的時(shí)候,就會(huì)進(jìn)入到Blocked狀態(tài),當(dāng)睡眠時(shí)間過了,I/O完成了,線程就會(huì)進(jìn)入到Runnable狀態(tài)。
6.當(dāng)這個(gè)線程調(diào)用了join(),這個(gè)線程的父線程就會(huì)被阻塞,一般父線程的任務(wù)會(huì)在子線程的任務(wù)之前執(zhí)行。但如果子線程調(diào)用了join(),那么父線程就必須等待子線程任務(wù)完成或者超時(shí)(join可以設(shè)置超時(shí)時(shí)間),父線程會(huì)進(jìn)入到Runnable,等待獲得CPU資源才能進(jìn)行往下執(zhí)行。
7.這是在多線程同步的情況下討論的,當(dāng)一個(gè)線程獲得CPU資源后,也就是進(jìn)入到了Running狀態(tài),在run()方法里調(diào)用了wait(),那么這個(gè)線程就會(huì)進(jìn)入到等待Blocked狀態(tài)。當(dāng)其他線程調(diào)用了notify()或者notifyAll()的時(shí)候,這個(gè)線程就會(huì)進(jìn)入到鎖定Blocked狀態(tài),當(dāng)其他線程釋放了鎖之后,該線程就可以回到Runable狀態(tài)了。
3.過程解析
總的來說,線程的生命周期有五個(gè)過程。分別是new,runnable,running,blocked和dead.
(1) New
當(dāng)創(chuàng)建Thread類的一個(gè)實(shí)例(對(duì)象)時(shí),此線程進(jìn)入New狀態(tài)。例如:Thread thread=new Thread();處于New狀態(tài)的線程有自己的內(nèi)存空間。
(2) Runnable
當(dāng)新建的線程對(duì)象調(diào)用start()方法的時(shí)候,線程處于Runnable狀態(tài),這時(shí)候的線程已經(jīng)具備了運(yùn)行條件,但還沒有分配到CPU,處于線程就緒隊(duì)列(盡管是采用隊(duì)列形式,事實(shí)上,把它稱為可運(yùn)行池而不是可運(yùn)行隊(duì)列。因?yàn)閏pu的調(diào)度不一定是按照先進(jìn)先出的順序來調(diào)度的),等待系統(tǒng)為其分配CPU。Runnable狀態(tài)并不是執(zhí)行狀態(tài),當(dāng)系統(tǒng)選定一個(gè)處于Runnable狀態(tài)的Thread對(duì)象后,它就會(huì)從等待執(zhí)行狀態(tài)進(jìn)入執(zhí)行狀態(tài),系統(tǒng)挑選的動(dòng)作稱之為“cpu調(diào)度”。
(3) Running
處于Runnable狀態(tài)的線程一旦獲得CPU,線程就進(jìn)入Running狀態(tài)并自動(dòng)調(diào)用自己的run方法。處于Running狀態(tài)的線程最為復(fù)雜,它可以變?yōu)镽unnable狀態(tài)、Blocked狀態(tài)和Dead狀態(tài)。
當(dāng)對(duì)在Running狀態(tài)的線程調(diào)用yield()方法,它就會(huì)讓出CPU資源,再次變?yōu)榫途w狀態(tài),當(dāng)然,也會(huì)出現(xiàn)這種情況,線程調(diào)用yield()方法,這個(gè)線程進(jìn)入到Runnable狀態(tài),他和其他線程都有機(jī)會(huì)被重新分配CPU資源,這里就有可能出現(xiàn)該線程調(diào)用yield()方法讓出CPU資源后,處于Runnable狀態(tài)的該線程又被分配到了CPU資源,又可以重新進(jìn)入到Running狀態(tài)。
當(dāng)發(fā)生如下情況是,線程會(huì)從Running狀態(tài)變?yōu)锽locked狀態(tài):
① 線程調(diào)用sleep()方法主動(dòng)放棄所占用的系統(tǒng)資源
② 線程調(diào)用一個(gè)阻塞式IO方法,在該方法返回之前,該線程被阻塞
③ 線程試圖獲得一個(gè)同步監(jiān)視器(synchronized鎖),但同步監(jiān)視器正被其他線程所持有
④ 線程在等待某個(gè)通知(notify)
⑤ 程序調(diào)用了線程的suspend方法將線程掛起。不過該方法容易導(dǎo)致死鎖,所以程序應(yīng)該盡量避免使用該方法。這個(gè)方法已經(jīng)廢棄了。
當(dāng)線程的run()方法執(zhí)行完,或者被強(qiáng)制性地終止,例如出現(xiàn)異常,或者調(diào)用了stop()、destroy()方法等等,就會(huì)從Running狀態(tài)轉(zhuǎn)變?yōu)镈ead狀態(tài)。stop()和destroy()方法已經(jīng)廢棄了,建議不要再使用了。
(4) Blocked
處于Running狀態(tài)的線程在某些情況下,如執(zhí)行了sleep()方法或等待I/O設(shè)備等資源,將讓出CPU并暫時(shí)停止自己的運(yùn)行,進(jìn)入阻塞狀態(tài)。在阻塞狀態(tài)的線程不能進(jìn)入Runnale隊(duì)列。只有當(dāng)引起阻塞的原因消除時(shí),如睡眠時(shí)間已到,或等待的I/O設(shè)備空閑下來,線程便轉(zhuǎn)入Runnale狀態(tài),重新到Runnale隊(duì)列中排隊(duì)等待,被系統(tǒng)選中后進(jìn)入到Running狀態(tài),線程便從原來停止的位置開始繼續(xù)運(yùn)行。
(5) Dead
當(dāng)線程的run()方法執(zhí)行完,或者被強(qiáng)制性地終止,就認(rèn)為它死去。這個(gè)線程對(duì)象也許是活的,但是,它已經(jīng)不是一個(gè)單獨(dú)執(zhí)行的線程。線程一旦死亡,就不能復(fù)生。如果在一個(gè)死去的線程上調(diào)用start()方法,會(huì)拋出java.lang.IllegalThreadStateException異常。