1.0、多線程學習——線程的狀態 java.lang.Thread.State

前言

體能狀態先於精神狀態,習慣先於決心,聚焦先於喜好。

從操作系統層面談線程的狀態

進程和線程的簡單介紹

在操作系統中,進程是資源分配的基本單位,線程是CPU調度的基本單位
一個進程可以包含多個線程,換句話說,多個線程之間可以共享一個進程佔用的硬件資源——當然,具體運行環節,每個線程依舊需要獨享一些資源。
進程的資源分配的操作相比線程而言要“重”,或者說要複雜、耗時。
線程之間的切換也是需要消耗一定的性能。

從寶貴的CPU資源來談線程的狀態

在整個計算機的硬件設施中,無論是從價格,還是容量的角度,最寶貴的算是CPU了,所以多線程編程環境下CPU的分配就是一個非常重要的特性。
在操作系統中,進程是資源分配基本單位,線程是CPU調度基本單位。
爲了滿足多個線程的併發運行,操作系統會爲每個線程分配一個時間片,得到時間片的線程可以運行,否則就需要線程進行等待。

進程和線程的狀態

線程同樣具有就緒、等待、執行三種基本狀態,同樣具有狀態之間的轉換關係。
當程序需要使用CPU時,由操作系統給線程分配時間片,在該時間內運行,如果程序中有其它操作(比如I/O操作,等待用戶從鍵盤輸入信息),那麼操作系統此時會將線程的狀態歸爲阻塞,不分配CPU資源,等到其它操作結束後,從新分配時間片,這個過程可以看出來,在CPU中程序其實是斷斷續續的執行的。
具體如下圖:

在這裏插入圖片描述

Java 的跨平臺特性

Java 是跨平臺的開發語言,當我們在 Java 代碼中使用進行多線程開發的時候,底層需要操作系統的具體實現。因爲 JVM 中間隔着一個操作系統,所以 Java 中的線程狀態和操作系統的線程狀態存在一些不同。

Java 中線程的狀態

Java 中並沒有進程的概念,而只有線程的概念。
Java 中線程的狀態和操作系統中線程的狀態有所不同,因爲 JVM 只能把相關程序通過本地方法棧,再通過執行引擎傳遞給操作系統來執行。
Java 中線程的狀態有 6 種,可以在 java.lang.Thread 中進行查看。
從下面這張狀態轉化圖可以看出來,JVM 無法完全控制線程是否阻塞,因爲在 RUNNABLE 這種狀態下,CPU 資源的分配是由操作系統進行的,所以 JVM 中RUNNING 狀態 有可能是阻塞的。
再一個,對於Java 中Blocked (阻塞)狀態,其表明線程需要等待獲得獲得再次獲得 monitor鎖(翻譯爲控制器鎖或內置鎖),之所以說再次,因爲在 Object.wait()之後,線程需要其他線程調用 Object.notify或者 Object.notifyAll進行喚醒

在這裏插入圖片描述

java.lang.Thread

Thread 類是我們常用的線程類之一,使用它需要重寫其中的run()方法。
Thread 實現了 Runnable 接口。
下面是源碼中對Thread 的簡單介紹:

  • thread 表示一個進程中線程的執行。JVM 允許一個應用同時擁有多個線程運行。
  • 每一個線程有一個優先級。優先級高的線程會被優先執行。線程允許被設置爲 daemon 線程,被設置爲 daemon的線程會駐留後臺,知道整個程序運行結束才退出。
  • 當 JVM 啓動的時候,一般而言只會有一個線程(main方法)。對於多線程的情況,JVM會執行所有的線程,直到下面的情況發生:
    [1]、Runtime的exit()方法被請求,並通過權限驗證
    [2]、所有的線程都不是 daemon 線程(後臺駐留線程)並且已經死亡;或者已經返回了run()方法的執行結果;或者拋出異常。
  • 創建線程的方法有兩種(其實不止兩種),第一種是繼承 Thread 類,第二種是實現 Runnable 接口.
  • 每一個線程都有一個名字,如果你在創建時不指定,那麼一個新名字會自動生成。

monitor 鎖

monitor鎖可以被翻譯爲 控制鎖,也叫內置鎖,表示所有Java對象自身可以作爲同步鎖的特性。多線程學習——內置鎖(監視器鎖)、對象 和 Synchronized 代碼塊

Java 中線程的狀態

參考 java.lang.Thread 中 State 的註釋可以得到以下內容

  • Java 中線程一共有6種狀態:NEW(新建)、RUNNABLE(運行)、BLOCKED(鎖池)、TIMED_WAITING(定時等待)、WAITING(等待)、TERMINATED(終止、結束)

  • Thread.State.NEW(新建):創建了線程,但是沒有調用 start()方法。

  • Thread.State.RUNNABLE(正在運行):調用了 start()方法,正在jvm中運行,但是可能正在等待操作系統的其他資源。

  • Thread.State.WAITING(等待):處於等待狀態的線程,正在等待另一個線程執行特定的操作,比如 Object.notify()或Object.notifyAll()。

  • Thread.State.TIMED_WAITING(定時等待),線程等待指定的時間後繼續執行。

  • Thread.State.BLOCKED(阻塞):等待獲取 監視器鎖(對象的內置鎖),可以是獲取synchronized 方法/代碼塊的監視器鎖,也可以是 wait()方法後,等待其他線程喚醒再次獲取 synchronized 的方法/代碼塊 的監視器鎖。

  • Thread.State.TERMINATED(結束或死亡):線程運行結束或者死亡。

Java 線程的阻塞和操作系統的阻塞

Java 線程中RUNNING 狀態也可能阻塞

上文在圖中已經畫出了 Java 線程RUNNING 狀態需要操作系統分配CPU資源,而CPU調度的過程可能是間歇式阻塞的,比如等待用戶I/O.

Java 線程的BLOCKED 阻塞狀態

Java 中線程可能處於WAITING、TIMED_WAITING、BLOCKED ,你可能說,大家都是等待,起那麼多名字幹嘛?
其實根源在於,BLOCKED 是明確沒有持有monitor鎖的狀態,如果想要進入 RUNNING狀態,需要獲取monitor鎖才行。
而 WAITING 和 TIMED_WAITING 狀態的線程可能進入 BLOCKED 狀態 ,也可能再次直接進入 RUNNING 狀態,區別在於命令。
Object.wait()和Object.wait(n)會釋放鎖,然後進入BLOCKED狀態
Thread.sleep(n)不會釋放鎖,線程狀態會由 TIMED_WAITING 再次進入 RUNNING
已經不推薦使用的 Thread.suspend()命令 不會釋放鎖資源,而是進入 WAITING 狀態,等待不推薦使用的 Thread.resume()來從新轉化爲 RUNNING 狀態。

參考資料

[1]、https://www.cnblogs.com/duanjiapingjy/p/9426825.html
[2]、https://www.cnblogs.com/GooPolaris/p/8079490.html
[3]、https://www.cnblogs.com/zbqhc/p/7624372.html

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