線程的生命週期狀態圖,及相應概念。

一、線程的生命週期
線程狀態轉換圖:

1、新建狀態(New)

用new關鍵字和Thread類或其子類建立一個線程對象後,該線程對象就處於新生狀態。處於新生狀態的線程有自己的內存空間,通過調用start方法進入就緒狀態(runnable)。

注意:不能對已經啓動的線程再次調用start()方法,否則會出現java.lang.IllegalThreadStateException異常。

2、就緒狀態(Runnable)

處於就緒狀態的線程已經具備了運行條件,但還沒有分配到CPU,處於線 程就緒隊列(儘管是採用隊列形式,事實上,把它稱爲可運行池而不是可運行隊列。因爲cpu的調度不一定是按照先進先出的順序來調度的),等待系統爲其分配 CPU。等待狀態並不是執行狀態,當系統選定一個等待執行的Thread對象後,它就會從等待執行狀態進入執行狀態,系統挑選的動作稱之爲“cpu調 度”。一旦獲得CPU,線程就進入運行狀態並自動調用自己的run方法。

提示:如果希望子線程調用start()方法後立即執行,可以使用Thread.sleep()方式使主線程睡眠一夥兒,轉去執行子線程。

3、運行狀態(Running)

處於運行狀態的線程最爲複雜,它可以變爲阻塞狀態、就緒狀態和死亡狀態。

處於就緒狀態的線程,如果獲得了cpu的調度,就會從就緒狀態變爲運行狀態,執行run()方法中的任務。如果該線程失去了cpu資源,就會又從運 行狀態變爲就緒狀態。重新等待系統分配資源。也可以對在運行狀態的線程調用yield()方法,它就會讓出cpu資源,再次變爲就緒狀態。

當發生如下情況是,線程會從運行狀態變爲阻塞狀態:

①、線程調用sleep方法主動放棄所佔用的系統資源

②、線程調用一個阻塞式IO方法,在該方法返回之前,該線程被阻塞

③、線程試圖獲得一個同步監視器,但更改同步監視器正被其他線程所持有

④、線程在等待某個通知(notify)

⑤、程序調用了線程的suspend方法將線程掛起。不過該方法容易導致死鎖,所以程序應該儘量避免使用該方法。

當線程的run()方法執行完,或者被強制性地終止,例如出現異常,或者調用了stop()、desyory()方法等等,就會從運行狀態轉變爲死亡狀態。

4、阻塞狀態(Blocked)

處於運行狀態的線程在某些情況下,如執行了sleep(睡眠)方法,或等待I/O設備等資源,將讓出CPU並暫時停止自己的運行,進入阻塞狀態。阻塞的情況分三種:

(一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖(synchronized)被別的線程佔用,則JVM會把該線程放入鎖池中。
(三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。

在阻塞狀態的線程不能進入就緒隊列。只有當引起阻塞的原因消除時,如睡眠時間已到,或等待的I/O設備空閒下來,線程便轉入就緒狀態,重新到就緒隊列中排隊等待,被系統選中後從原來停止的位置開始繼續運行。有三種方法可以暫停Threads執行。

5、死亡狀態(Dead)

需要說明的是,synchronized鎖和調用wait()的對象應爲同一對象!否則會報java.lang.IllegalMonitorStateException錯誤。正確方式如下:
 

public synchronized static void function01() { //類鎖 
    try { 
        Test.class.wait();//本類的wait池            
    } catch (InterruptedException e) { 
        e.printStackTrace(); 
    } 
} 
public void function02() { 
    synchronized (lock) {//lock鎖 
        try { 
            lock.wait();//同樣爲lock鎖的wait池 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
    } 
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章