线程生命周期的理解
線程的生命周期
線程的生命周期有五個狀態:
新建狀態(New)
就緒狀態(Runnable)
運行狀態(running)
阻塞狀態(Blocked)
死亡狀態(dead)
新建狀態:
當程序使用new關鍵字創建了一個線程之后,該線程就處于就緒狀態,此時由JVM分配內存,并初始化成員變量的值,此時程序不會執行線程執行體。就緒狀態:
當程序調用start()方法的時候,程序處于就緒狀態,JVM會為其創建方法調用棧和程序計數器,處于這個狀態的線程還沒開始在運行,表示該線程可以運行了。
運行狀態:
如果程序處于就緒狀態并且獲得了CPU的執行權,則程序開始自動執行run()方法的線程執行體,則該線程處于運行狀態,
堵塞狀態:
在某當某個線程調用了它的sleep()或yield()方法后會放棄所占用的資源,此時線程進入堵塞狀態:
線程進入堵塞狀態的情況:
線程調用sleep()方法主動放棄所占用的處理器資源。
線程調用了一個阻塞式的IO方法,在該方法之前,該線程被堵塞。
線程試圖獲得一個同步監視器,但該監視器正在被其他線程所占用。
線程在等等在某個通知(motify)。
程序調用了該線程的suspend()方法將該線程掛起,但該方法容易導致死鎖,因該盡量避免使用。
當程序正在執行的線程被堵塞之后,其他的線程可以獲得執行的機會。被堵塞的線程會在合適的時候重新進入就緒狀態,注意是需要重新進入就緒狀態而不是運行狀態,因為線程需要繼續搶奪CUP的執行權,
發生以下情況可以解除堵塞讓線程重新進入就緒狀態:
調用sleep()方法線程經過了指定的時間。
線程調用的阻塞式IO方法已經返回。
線程成功地獲得了試圖取得的同步監視器的執行權。
處于掛起狀態的線程被調用了resume()恢復方法。
總結:
線程從阻塞狀態只能進入就緒狀態,無法直接進入運行狀態,而就緒狀態和運行狀態的轉換通常不受程序控制,而是由系統線調度所決定的,當線程獲得CUP執行權的時候,線程進入運行狀態,當線程失去CUP執行權的時候,線程就如就緒狀態,但是當線程放棄CUP的執行權的時候線程會進入堵塞狀態,這時候需要線程重新進入就緒狀態,如此依次循環,直單線程任務完成。
線程死亡:
線程如果有以下三種狀態線程就處于死亡狀態:
? run()或者call()方法執行完成,線程正常結束。 ? 線程拋出一個未捕獲的Exceptionh或者Error/
? 直接調用該線程的stop()方法來結束該線程——該方法容易等導致死鎖,不建議使用。
當主線程結束時,其他線程并不會受到影響,并不會隨之而結束,一旦子線程啟動起來,他就擁有了和主線程一樣的的地位,不會受到主線程的影響。
為了測試某個線程處于何種狀態,可以調用線程對象的isAliver()方法,當線程處于就緒、運行、阻塞三種狀態,該方法返回true,當線程處于新建、死亡兩種狀態時,該方法將放回false.
不要試圖對一個死亡的線程調用start()方法使他重新啟動,死亡就是是死亡,該線程將不可以再此作為線程執行。
程序嘗試調用死亡線程:public class StartDead {public static void main(String[] args) {Thread thread=new Thread(new Runnable(){@Overridepublic void run() {for (int i = 0; i <100 ; i++) {System.out.println(Thread.currentThread().getName()+":"+i);}}});thread.start();//判斷啟動或線程的狀態System.out.println(thread.isAlive());for (int i = 0; i <100 ; i++) {System.out.println(Thread.currentThread().getName()+":"+i);}//當分支線程處于死亡狀態,試圖再次啟動該線程,會引發異常thread.start();} }注意: 不要對處于死亡狀態的線程再度調用start()方法,程序只能對新建狀態的線程調用start()方法,對新建狀態的線程兩次調用tart()方法是錯誤的,這回引發IIIegaTheardStartException異常。
總結
- 上一篇: 解析java匿名内部类
- 下一篇: java线程的创建和启动深度解析