Java多線程——線程的優先級和生命周期
摘要:本文主要介紹了線程的優先級以及線程有哪些生命周期。
部分內容來自以下博客:
https://www.cnblogs.com/sunddenly/p/4106562.html
線程的優先級
線程的優先級及設置
線程的優先級是為了在多線程環境中便於系統對線程的調度,優先級越高先執行機會越大,並不是一定先執行。
線程的優先級可以理解為線程搶占CPU時間片的概率,並不能保證優先級高的線程一定會先執行。
不同的系統有不同的線程優先級的取值范圍,同一個優先級在不同的系統里的值可能是不同的。
一個線程的優先級設置遵從以下原則:
線程創建時,子繼承父的優先級。
線程創建后,可通過調用setPriority()方法改變優先級。
線程的優先級是1-10之間的正整數,線程優先級最高為10,最低為1,默認為5。
1- MIN_PRIORITY
10-MAX_PRIORITY
5-NORM_PRIORITY
線程的調度策略
線程調度器選擇優先級最高的線程運行。但是,如果發生以下情況,就會終止線程的運行:
線程體中調用了yield()方法,讓出了對CPU的占用權。
線程體中調用了sleep()方法,使線程進入睡眠狀態。
線程由於I/O操作而受阻塞。
另一個更高優先級的線程出現。
在支持時間片的系統中,該線程的時間片用完。
線程的生命周期
線程的生命周期:一個線程從創建到消亡的過程。
如下圖,表示線程生命周期中的各個狀態:
新建狀態(New)
當線程對象對創建后,即進入了新建狀態。
就緒狀態(Ready)
當調用線程對象的start()方法,線程即進入就緒狀態。處於就緒狀態的線程,只是說明此線程已經做好了准備,隨時等待CPU調度執行,並不是說執行了start()此線程立即就會執行。
當調用線程的yield()方法時,線程從運行狀態轉換為就緒狀態,但接下來CPU調度就緒狀態中的哪個線程具有一定的隨機性。
運行狀態(Running)
當CPU開始調度處於就緒狀態的線程時,此時線程才得以真正執行,即進入到運行狀態。
注:就緒狀態是進入到運行狀態的唯一入口,也就是說,線程要想進入運行狀態執行,首先必須處於就緒狀態中。
阻塞狀態(Blocked)
處於運行狀態中的線程由於某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才有機會再次被CPU調用以進入到運行狀態。根據阻塞產生的原因不同,阻塞狀態又可以分為三種。
等待阻塞:運行狀態中的線程執行wait()方法,使本線程進入到等待阻塞狀態。
同步阻塞:線程在獲取synchronized同步鎖失敗(因為鎖被其它線程所占用),它會進入同步阻塞狀態。
其他阻塞:通過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、I/O處理完畢時,線程重新轉入就緒狀態。
死亡狀態(Dead)
線程執行完了或者因異常退出了run()方法,該線程結束生命周期。
線程的上下文切換
對於單核CPU來說,CPU在一個時刻只能運行一個線程,當在運行一個線程的過程中轉去運行另外一個線程,這個叫做線程上下文切換。
由於當前線程的任務在切換的時候可能沒有執行完畢,所以在切換時需要保存線程的運行狀態,以便下次切換回來的時候能夠回到切換時的運行狀態,繼續進行操作。一般來說,線程上下文切換過程中會記錄指令寄存器、程序計數器、累加寄存器等其他數據。指令寄存器保留了線程在切換時執行到了哪條指令,以便繼續運行。程序計數器存儲了下一條指令在主存儲器中的地址。累加寄存保存了程序的運算結果,以及變量的值。
雖然多線程可以使得任務執行的效率得到提升,但是由於在線程切換時同樣會帶來一定的開銷代價,並且多個線程會導致系統資源占用的增加,所以在進行多線程編程時要注意這些因素。