執行緒狀態

辉辉、發表於2024-08-14

執行緒的五種?六種狀態?

五種狀態(從作業系統的層面描述)

執行緒的五種狀態是從作業系統的層面來描述的
在這裡插入圖片描述

  • 【初始狀態】:僅是在語言層面建立了執行緒物件,還未與作業系統執行緒關聯。栗子:java中new了一個Thread物件,但是沒有呼叫它的start方法。
  • 【可執行狀態(就緒狀態)】:指該執行緒已被建立(與作業系統執行緒關聯),可由cpu排程執行。栗子:java中呼叫一個執行緒物件的start方法,但是執行緒還沒有獲取cpu時間片。
  • 【執行狀態】:指獲取了CPU時間片執行中的狀態。栗子:執行緒獲取了cpu時間片正在執行執行緒中程式碼的那些執行緒,如開啟start方法後,執行其中run方法裡的程式碼塊的執行緒。
    • 當CPU時間片用完,會從[執行狀態]轉換至[可執行狀態],會導致執行緒的上下文切換(執行緒從使用cpu到不使用cpu叫做執行緒的上下文切換)
  • 【阻塞狀態】:如果呼叫了阻塞API,如BIO讀寫檔案,這時該執行緒實際不會用到CPU,會讓出cpu時間片,會導致執行緒上下文切換,進入【阻塞狀態】
    • 等BIO操作完畢,會由作業系統喚醒阻塞的執行緒,轉換至[可執行狀態]
    • 與[可執行狀態]的區別是,對[阻塞狀態]的執行緒來說只要它們一-直不喚醒,排程器就一-直不會考
      慮排程它們。喚醒之後執行緒不會立刻進入執行狀態,而是進入可執行狀態,等待執行緒獲取cpu時間片然後才會進入執行狀態。
  • 【終止狀態】:表示執行緒已經執行完畢,生命週期已經結束,不會再轉換為其它狀態。

執行緒的六種狀態(javaAPI層面描述)

執行緒的六種狀態(javaAPI層面描述)

哪來的六種狀態?多了一種?親生的?老王?答案呼之欲出,令人倒吸一口冷氣。
其實執行緒的6種狀態是從javaAPI層面來描述的,Thread.State列舉,它把執行緒分為6中狀態

我們來看下原始碼,Thread的1742行程式碼開始。所以執行緒的6中狀態一般都是從java的層面來描述的。javaAPI確定的把執行緒分成了6中狀態。

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

在這裡插入圖片描述

  • 【NEW】:執行緒剛被建立,但是還沒有呼叫start()方法.
  • 【RUNNABLE】:當呼叫了start()方法之後,注意, Java API層面的RUNNABLE狀態涵蓋了作業系統層面的
    [可執行狀態]、[執行狀態] 和[阻塞狀態] (由於 BIO導致的執行緒阻塞,在Java裡無法區分,仍然
    認為是可執行)
  • 【TERMINATED】: 終止狀態。執行緒內程式碼已經執行結束,它不會再轉為其他狀態。

程式碼實現java中執行緒的6種狀態

以下程式碼中所有獲取執行緒狀態之前都讓主執行緒(main)方法睡了一會,是因為在主執行緒中獲取執行緒的狀態時,確保執行緒進入相應的睡眠或者阻塞以得到正確的狀態,否則執行緒還沒有睡眠就獲取它們的狀態,那麼執行緒只要是呼叫了start方法就都是RUNNABLE狀態了。

NEW(初始狀態)

執行緒的就緒狀態:只是建立了執行緒物件,沒有呼叫start方法

public class ThreadStatus {
    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("建立狀態");
            }
        });
        // 執行緒的就緒狀態:只是建立了執行緒物件,沒有呼叫start方法
        System.out.println("就緒狀態:" + t1.getState());
    }

在這裡插入圖片描述

RUNNABLE(執行狀態)

這裡的執行狀態是java中的執行狀態:相當與作業系統中的,可執行狀態(就緒狀態),執行狀態,阻塞狀態。

// java中的執行狀態RUNNABLE
    public static void t2() {
        // 執行狀態:
        // java中的執行狀態:相當與作業系統中的,可執行狀態(就緒狀態),執行狀態,阻塞狀態
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {

                }
            }
        });
        t2.start();
        System.out.println("執行狀態 :" + t2.getState());
    }

在這裡插入圖片描述

TERMINATED(終止狀態)

// TERMINATED(終止狀態)
    public static void t3() throws InterruptedException {
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("終止狀態:");
            }
        });
        t3.start();
        // 主執行緒睡1s,此時執行緒t3早已執行完畢,便是終止狀態
        Thread.sleep(1000);
        System.out.println("終止狀態:" + t3.getState());
    }

在這裡插入圖片描述

TIMED_WAITING(有時限的等待)

java中的阻塞狀態不會得到任務排程器的排程,也就不會得到cpu時間

public static void t4() throws InterruptedException {
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (ThreadStatus.class) {
                    try {
                        Thread.sleep(10000000); // timed_waiting
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t4.start();
        Thread.sleep(500);
        System.out.println(t4.getState());
    }

在這裡插入圖片描述

WAITING(無時限的等待)

java中的阻塞狀態不會得到任務排程器的排程,也就不會得到cpu時間

 // waiting
    public static void t5 () {
        Thread t5 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {

                }
            }
        });
        t5.start();
        Thread t6 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // t5是個死迴圈,join方法就是等待呼叫的那個執行緒執行完再執行下面的任務,所以t6會一直等待
                    t5.join(); // 因為這種等待就沒有加時限,所以是waiting
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t6.start();
        System.out.println(t6.getState());
    }

在這裡插入圖片描述

BLOCKED(沒有獲取到鎖)

執行緒沒有獲取到鎖就是blocked狀態

 // blocked
    public static void t6() throws InterruptedException {
        Thread t7 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (ThreadStatus.class) {
                    try {
                        Thread.sleep(1000000); // timed_waiting
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t7.start();

        Thread t8 = new Thread(new Runnable() {
            @Override
            public void run() {
                // blocked
                // t7已經對ThreadStatus加了鎖,但是在t7還沒有釋放鎖資源之前,t8是拿不到鎖資源的,於是就是
                synchronized (ThreadStatus.class) {
                    try {
                        Thread.sleep(1000000); // timed_waiting
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t8.start();
        Thread.sleep(500);
        System.out.println("" + t8.getState());
    }

在這裡插入圖片描述

相關文章