一、線程生命週期的五種狀態
線程從創建、運行到結束總是處於下面五個狀態之一:新建狀態、就緒狀態、運行狀態、阻塞狀態及死亡狀態。
新建狀態(New):新創建了一個線程對象,Java虛擬機爲其分配內存。
就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。就緒狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
運行狀態(Running):就緒狀態的線程獲取了CPU,執行run()方法中的程序代碼。
阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的情況分三種:
等待阻塞(WAITING):運行的線程執行wait()方法,JVM會把該線程放入等待池中。
同步阻塞(Blocked):運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。
超時阻塞(TIME_WAITING):運行的線程執行sleep(long)或join(long)方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。
死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。
二、線程狀態轉換
首先,線程對象創建後,虛擬機只是爲其分配內存,進入新建狀態,線程對象與其他對象的創建相同,並不會表現出線程對象的特徵。當線程對象的start()方法調用後,線程進入就緒狀態,Java虛擬機會爲其創建方法調用棧和程序計數器,處於就緒狀態的線程並沒有開始運行,只是表示該線程最好了準備,可以運行了,運行的時機取決於JVM裏線程調度器的調度。
之後,如果處於就緒狀態的線程獲得了CPU,線程進入運行狀態,開始執行run()方法的線程執行體,這個過程是由系統調度的,開發者無法控制。線程的執行過程中可能會被中斷,目的是使其他線程獲得執行的機會,正在運行的線程也可以調用線程控制方法放棄所佔用的資源,線程進入阻塞狀態,並在合適時候進入就緒狀態。
最後,處於運行狀態的線程會以下列三種方式結束,進入死亡狀態。
- run()方法或者call()方法執行結束,線程正常結束。
- 線程拋出未捕獲的異常。
- 調用線程的stop()方法結束該線程。