JAVA基礎知識之多線程——線程的生命周期(狀態)


線程有五個狀態,分別是新建(New)、就緒(Runnable)、運行(Running)、阻塞(Blocked)和死亡(Dead)。

新建和就緒

程序使用new會新建一個線程,new出的對象跟普通對象一樣,JVM會為其分配內存,初始化成員變量等,此時線程並沒有運行,而是就是新建狀態。

當線程對象調用start后,線程將進入就緒狀態。JVM會為其創建函數調度棧和計數器,但此時線程依然沒有運行,而是等待獲取CPU執行片

下面的例子可以證明當線程對象調用start后,並不一定立即執行,

for (int i=0; i<50; i++) {
	System.out.println(Thread.currentThread().getName()+" "+i);
	if(i==20){
		SecondThread st = new SecondThread();
		new Thread(st, "new thread 1").start();
	}
}

上面是在main中創建子線程,下面是運行結果,

...

main 18
main 19
main 20
main 21
main 22
new thread 1 0
main 23
new thread 1 1
main 24
new thread 1 2
main 25

...

從上面的運行結果可以看到,原本在main中i=20的時候新建了一個子線程,並立即調用了start()使線程進入就緒狀態,但是一直等到i=22的時候,子線程才開始運行,所以子線程何時會開始執行取決於CPU執行片的分配,由JVM調度器決定。

運行和阻塞狀態

當就緒狀態的線程獲取了CPU執行片的之后,就進入運行狀態,但是在執行過程中,可能會因為以下原因使線程進入阻塞狀態,

  • CPU執行片已經用完,JVM切換到其他線程執行
  • 線程調用sleep()
  • 線程調用了阻塞IO方法,該方法返回之前,線程會一直阻塞
  • 線程試圖獲取被其他線程持有的同步監視器
  • 線程在等待某個通知
  • 程序調用了線程的suspend()將線程掛起。(容易死鎖,不推薦)

線程從運行進入阻塞狀態之后,接着只能繼續阻塞或者再次進入就緒狀態,下面情況會使線程由阻塞狀態重新進入就緒狀態,

  • 線程調用的slee()經過了指定時間
  • 線程調用的阻塞IO方法返回
  • 線程成功獲取同步監視器
  • 線程收到其他線程發出的通知
  • 被掛起(suspend)的線程又被程序調用了resume方法

下圖演示了線程狀態轉換過程,

注意從上圖可知,

線程從阻塞狀態只能進入就緒狀態,

通常情況下,就緒狀態和運行狀態的轉換是不受程序控制的,而是由JVM線程調度機制控制的

yield()方法可以讓運行狀態的線程進入就緒狀態

線程死亡

線程結束后就處於死亡狀態,線程會以如下三種方式結束,

  • run()或call()正常執行完成,線程正常結束
  • 線程拋出一個未捕獲的Exception或Error
  • 直接調用線程的stop()方法結束線程,容易死鎖

注意,子線程一旦啟動,其地位和主線程是一樣的,所以一旦主線程結束了,子線程不會受影響,不會跟着結束

線程對象的isAlive()方法在就緒,運行,阻塞時返回true,在新建,死亡時返回false

對已經死亡的線程調用start()是無效的,會拋出異常。 死亡的線程不可再次作為線程來執行。

對於新建的線程,調用兩次start()方法也會拋出異常

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM