?【Java技術指南】「難點-核心-遺漏」Java線程狀態(tài)流轉(zhuǎn)及生命周期的技術指南(知識點串燒)!

前提介紹

本章主要介紹相關線程聲明周期的轉(zhuǎn)換機制以及聲明周期的流轉(zhuǎn)關系以及相關AQS的實現(xiàn)和相關的基本原理,配合這相關官方文檔的中英文互譯的介紹。

線程狀態(tài)流轉(zhuǎn)及生命周期

當線程被創(chuàng)建并啟動以后,它既不是一啟動就進入了執(zhí)行狀態(tài),也不是一直處于執(zhí)行狀態(tài)。在線程的生命周期中,它要經(jīng)過新建(New)、就緒/可運行狀態(tài)(Runnable)、阻塞(Blocked)和等待(Wait)、時間等待(Time_wait)、終止狀態(tài)(Terminate)六種狀態(tài)。尤其是當線程啟動以后,它不能一直“霸占”著CPU獨自運行,所以CPU需要在多條線程之間切換,于是線程狀態(tài)也會多次在運行、阻塞之間切換。

下圖借鑒于官方網(wǎng)站:

生命周期的六種狀態(tài)

一個事物從出生的那一刻開始到最終死亡中間的整個過程.在事物的漫長的生命周期過程中,總會經(jīng)歷不同的狀態(tài)(嬰兒狀態(tài)/青少年狀態(tài)/中年狀態(tài)/老年狀態(tài)...).線程也是有生命周期的,也是存在不同的狀態(tài)的,狀態(tài)相互之間的轉(zhuǎn)換。

線程對象的狀態(tài)存放在Thread類的內(nèi)部類(State)中:

 public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

注意:Thread.State類其實是一個枚舉類.因為線程對象的狀態(tài)是固定的,只有6種,此時使用枚舉來表示是。


新建(new Thread)

  • 當創(chuàng)建Thread類的一個實例(對象)時,此線程進入新建狀態(tài)(未被啟動)。
  • 使用new創(chuàng)建一個線程對象,僅僅在堆中分配內(nèi)存空間,在調(diào)用start方法之前。 新建狀態(tài)下,線程壓根就沒有啟動,僅僅只是存在一個線程對象而已.Thread t = new Thread();
  • 此時t就屬于新建狀態(tài)當新建狀態(tài)下的線程對象調(diào)用了start方法,此時從新建狀態(tài)進入可運行狀態(tài).線程對象的start方法只能調(diào)用一次,否則報錯:IllegalThreadStateException.

例如

Thread  t1=new Thread();

可運行(runnable)

分成兩種子狀態(tài),ready和running。分別表示就緒狀態(tài)和運行狀態(tài)。

就緒狀態(tài)

線程對象調(diào)用start方法之后,等待JVM的調(diào)度(此時該線程并沒有運行),這時候線程處于等待CPU分配資源階段,誰先搶的CPU資源,誰開始執(zhí)行,換句話說線程已經(jīng)被啟動,正在等待被分配給CPU時間片,也就是說此時線程正在就緒隊列中排隊等候得到CPU資源。

運行狀態(tài)

線程對象獲得JVM調(diào)度,如果存在多個CPU,那么允許多個線程并行運行

image
  • 被轉(zhuǎn)換成Terminated狀態(tài),比如調(diào)用 stop() 方法;
  • 被轉(zhuǎn)換成Blocked狀態(tài),比如調(diào)用了sleep, wait 方法被加入 waitSet 中;
  • 被轉(zhuǎn)換成Blocked狀態(tài),如進行 IO 阻塞操作,如查詢數(shù)據(jù)庫進入阻塞狀態(tài);
  • 被轉(zhuǎn)換成Blocked狀態(tài),比如獲取某個鎖的釋放,而被加入該鎖的阻塞隊列中;
  • 該線程的時間片用完,CPU 再次調(diào)度,進入Runnable狀態(tài);
  • 線程主動調(diào)用 yield 方法,讓出 CPU 資源,進入Runnable狀態(tài)

例如

t1.start();

運行(running)他也從屬于Runnable狀態(tài),但不在總體狀態(tài)之內(nèi),屬于邏輯狀態(tài)機制

當就緒的線程被調(diào)度并獲得CPU資源時,便進入運行狀態(tài),run方法定義了線程的操作和功能,此時除非此線程自動放棄CPU資源或者有優(yōu)先級更高的線程進入,線程將一直運行到結(jié)束。

[圖片上傳失敗...(image-8d4fcd-1631164223141)]

注意:

image

Runnable狀態(tài)的線程無法直接進入Blocked狀態(tài)和Terminated狀態(tài)的。只有處在Running狀態(tài)的線程,換句話說,只有獲得CPU調(diào)度執(zhí)行權的線程才有資格進入Blocked狀態(tài)和Terminated狀態(tài),Runnable狀態(tài)的線程要么能被轉(zhuǎn)換成Running狀態(tài),要么被意外終止。

堵塞(blocked)

正在運行的線程因為某些原因放棄CPU,暫時停止運行,就會進入阻塞狀態(tài).此時JVM不會給線程分配CPU,直到線程重新進入就緒狀態(tài),才有機會轉(zhuǎn)到運行狀態(tài).阻塞狀態(tài)只能先進入就緒狀態(tài),不能直接進入運行狀態(tài)。

阻塞狀態(tài)的兩種情況:

  1. 當A線程處于運行過程時,試圖獲取同步鎖時,卻被B線程獲取.此時JVM把當前A線程存到對象的鎖池中,A線程進入阻塞狀態(tài).
  2. 當線程處于運行過程時,發(fā)出了IO請求時,此時進入阻塞狀態(tài).

由于某種原因?qū)е抡谶\行的線程讓出CPU并暫停自己的執(zhí)行,即進入堵塞狀態(tài)。

[圖片上傳失敗...(image-1ca0eb-1631164223141)]

  • 被轉(zhuǎn)換成Terminated狀態(tài),比如調(diào)用 stop() 方法,或者是 JVM 意外 Crash;
  • 被轉(zhuǎn)換成Runnable狀態(tài),阻塞時間結(jié)束,比如讀取到了數(shù)據(jù)庫的數(shù)據(jù)后;
  • 完成了指定時間的休眠,進入到Runnable狀態(tài);
  • 正在wait中的線程,被其他線程調(diào)用notify/notifyAll方法喚醒,進入到Runnable狀態(tài);
  • 線程獲取到了想要的鎖資源,進入Runnable狀態(tài);
  • 線程在阻塞狀態(tài)下被打斷,如其他線程調(diào)用了interrupt方法,進入到Runnable狀態(tài);

等待狀態(tài)(waiting)

(等待狀態(tài)只能被其他線程喚醒):

此時使用的無參數(shù)的wait方法,

  1. 當線程處于運行過程時,調(diào)用了wait()方法,此時JVM把當前線程存在對象等待池中.

計時等待狀態(tài)(timed waiting)

(使用了帶參數(shù)的wait方法或者sleep方法)

  1. 當線程處于運行過程時,調(diào)用了wait(long time)方法,此時JVM把當前線程存在對象等待池中.
  2. :當前線程執(zhí)行了sleep(long time)方法.

終止狀態(tài)(terminated)

通常稱為死亡狀態(tài),表示線程終止.

  1. 正常執(zhí)行完run方法而退出(正常死亡).
  2. 遇到異常而退出(出現(xiàn)異常之后,程序就會中斷)(意外死亡).
  3. JVM 異常結(jié)束,所有的線程生命周期均被結(jié)束。

線程一旦終止,就不能再重啟啟動,否則報錯(IllegalThreadStateException).

不推薦使用的線程方法

在Thread類中過時的方法(因為存在線程安全問題,所以棄用了):

  • void suspend() :暫停當前線程
  • void resume() :恢復當前線程
  • void stop() :結(jié)束當前線程

給大家結(jié)合官網(wǎng)在進行一個中文解釋的狀態(tài)流轉(zhuǎn)圖:

image.png
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容