線程生命週期和線程狀態 - 1

“嗨,阿米戈!”

“我們要開始一個新話題:線程。”

“讓我們開始吧,今天我們將研究線程運行時Thread對象經過(或可能經過)的狀態。”

“阿米戈,你現在能說出多少個州?”

“兩個。第一個是調用 start() 方法之前的線程:對象存在,但線程尚未激活。第二個是調用 start() 方法之後:當線程正在做某事時重要的。”

“你說得對——有這樣的區別。這些狀態被稱為newrunning,但這只是開始。”

“首先,在某個時刻線程將結束運行,這意味著可能存在Thread對象存在,但線程不處於新建或運行狀態的情況。”線程結束運行的這種狀態稱為終止了。”

“但還有更多。不要忘記在任何給定時間實際上只有一個線程在運行。看起來同時工作的實際上是處理器不斷地從一個線程跳到另一個線程。當線程似乎是正在運行,但實際上是在等待輪到它:它被稱為ready-to-run。作為一個線程工作,它不斷地從running切換到ready,然後在它再次激活時返回到running 。

“調用start () 方法後,線程立即被分配到準備運行狀態,並放置在 JVM 切換的共享線程列表中。”

” 那也不太難,在它開始運行之前,它有新的狀態。它運行完之後,它就終止了。當它運行時,線程處於運行狀態;然後在等待時,它處於就緒狀態”

“你的簡潔是驚人的,但你是對的。”

”但是還有更多。線程可以被阻塞。例如,當您進入同步塊時。如果一個線程到達標記為同步的代碼塊並且另一個線程正在使用它,那麼我們的線程將進入阻塞狀態並等待用於釋放對象的互斥鎖(鎖)。”

“這是各州的情況:”

線程生命週期和線程狀態 - 2

“但還有更多。還有一個單獨的狀態,叫做等待。這是當一個線程沒有被阻塞,但也沒有準備好的時候。例如,當你在另一個線程上調用join () 方法時。”

當我們在另一個 Thread 對像上調用 join() 時,就好像我們的線程“加入”了它,但實際上它只是在等待另一個線程完成。

“此外,還有wait () 方法(來自 wait/notify/notifyAll 三重奏方法),它會在線程被調用時將切換到等待狀態。”

“哇哦。”

“等一下!還有更多。例如,線程可以通過調用 sleep 方法進入睡眠狀態。為此還有一個單獨的狀態。它稱為 « timed waiting »。 « timed waiting »表示線程正在等待某事一個有限的時間。如果你調用一個帶參數的等待方法,比如 wait(timeout) 或 join(timeout),那麼線程將進入定時等待狀態。”

“這是完整的圖表:”

線程生命週期和線程狀態 - 3

“嗯,就這些嗎?或者還有10個更有趣的狀態?”

“現在,就是這樣。”

“實際上,你可以只記住第一個圖表。它更簡單。但第二個更準確。”

“奇怪,網上有很多Thread狀態圖,而且都不一樣。”

“這就是我給你這張圖的原因——它是最完整、最正確的。”

“在這個圖中,就緒狀態和運行狀態組合在一個稱為 runnable 的塊中。你知道為什麼嗎?”

“沒有。我還是第一次見到這樣的東西。”

Thread類有一個名為State 的內部類,以及一個public State getState()方法。”

例子
public enum State
{
 NEW,
 RUNNABLE,
 BLOCKED,
 WAITING,
 TIMED_WAITING,
 TERMINATED;
}

“你總是可以在Thread對像上調用getState () 方法,並找出它的當前狀態。而且,當然,它將是 State 枚舉值之一。”

“我明白了。所以,真正的狀態在 JVM 內部,但也有一些狀態可以使用 State getState() 方法通過 Java 代碼訪問。”

“我會在什麼情況下使用它?”

“很可能,永遠不會。”

“但你必須知道線程內部發生了什麼。否則,你會遇到很多錯誤,而且你甚至無法猜出是什麼導致了它們。”

“此外,雇主喜歡在面試時詢問線程狀態。”