1. 程式人生 > 其它 >執行緒執行過程中的狀態

執行緒執行過程中的狀態

1 執行緒執行過程中的狀態

  1. new 初始化狀態
  2. runnalbe 可執行/執行狀態
  3. blocked 阻塞狀態
  4. waiting 等待狀態,無時間限制
  5. timed_waiting 超時等待,有時間限制
  6. terminated 終止狀態

1.1 各個狀態介紹

1.1.1 new 初始化狀態

實現Runnable介面和繼承Thread可以得到一個執行緒類,從而可以new一個例項出來,執行緒進入初始化。

    public class ThreadTest extends Thread{
        private String name;

        public ThreadTest(String name){this.name = name}

        public void run(){
            for(int i = 1; i < 11; i++){
                System.out.println(Thread.currentThread().getName() + " Thread " + i);
            }
        }

        public static void main(String[] args){
            ThreadTest t1 = new ThreadTest("thread1");
            ThreadTest t2 = new ThreadTest("thread2");
            ThreadTest t3 = new ThreadTest("thread3");
            t1.start();
            t2.start();
            t3.start();
        }
    }
    public class TestRunnable implements Runnable{
        public void run(){
            for(int i = 1; i < 11; i++){
                System.out.println(Thread.currentThread().getName() + " Thread " + i);
            }
        }

        public static void main(String[] args){
            ThreadTest t1 = new ThreadTest("thread1");
            ThreadTest t2 = new ThreadTest("thread2");
            ThreadTest t3 = new ThreadTest("thread3");
            t1.start();
            t2.start();
            t3.start();
        }
    }

1.1.2 Runnable 就緒,執行中的狀態

  1. 就緒狀態只是說你自己在執行,排程程式沒有選到你,你就永遠是就緒狀態。
  2. 呼叫執行緒的start()方法,執行緒進入就緒狀態
  3. 當前執行緒slee()方法結束,其他程序join()結束,等待使用者輸入完畢,某個執行緒拿到物件鎖,這些執行緒也將進入就緒狀態。
  4. 當前執行緒時間片用完了,呼叫當前執行緒的yield()方法,當前執行緒進入就緒狀態。
  5. 鎖池裡的執行緒拿到物件鎖後,進入就緒狀態。

1.1.3 Running 執行中狀態

執行緒排程程式可以從執行池中選擇一個執行緒作為當前執行緒時,執行緒進入執行狀態。

這也是執行緒進入執行狀態的唯一方式。

1.1.4 Blocked 阻塞狀態

阻塞狀態是指執行緒阻塞在進入synchronized關鍵字修飾的方法或程式碼塊(獲取鎖)之前的狀態。

1.1.5 Waiting 等待狀態

呼叫sleep()或者wait()方法後,執行緒處於waiting狀態,等待被喚醒。

1.1.6 timed_waiting 等待超時狀態

呼叫sleep()或者wait()方法後,執行緒處於timed_waiting狀態,等待被喚醒,或者超時被自動喚醒。

1.1.7 treminated 終止狀態

  1. 當前執行緒的run方法完成時,或者主執行緒的main方法完成時,我們就認為他終止了。這個物件也許是活的,但是他已經不是一個獨立執行的執行緒。執行緒一旦停止,就不能復生。
  2. 在一個終止執行緒上呼叫start方法,會丟擲java.long.IllegalThreadStateException異常

1.2 執行緒之間狀態的切換

1.2.1 new -> runnable

  • 實現runnable介面,或者整合thread類,可以獲得一個執行緒類,建立這個類的例項物件,就是new
  • new狀態的執行緒不會被作業系統排程,也不會被執行
  • 呼叫的這個執行緒的start方法,將new狀態轉換成runnable狀態

1.2.2 runnable -> block -> runnable

  • runnable執行緒獲得cpu執行時間,執行run方法,進入running狀態
  • running執行緒進入synchronized同步塊,可能進行同步阻塞或IO阻塞,進入blocked狀態
  • block執行緒同步synchronized同步塊,可能進行同步塊釋放或IO完成,進入runnable狀態

只有當執行緒等待synchronized的隱形鎖時,執行緒才會從runnable向blocked狀態轉換。

被synchronizded關鍵字修飾的方法、程式碼,在同一時刻,只允許一個執行緒執行。

所以在這種情況下,等待的執行緒就會從runnable變為block,當等待的執行緒獲得synchronized隱式鎖時,就會從block狀態轉到如runnable。

1.2.3 runnable -> running -> waiting -> runnable

  • 有三種情況會觸發執行緒從runnable轉到waiting
    • 獲得synchronized的執行緒呼叫Object.wait()
    • 呼叫執行緒同步Thread.join方法
      • 執行緒A在runnable。得到cpu執行時間後,變為running
      • 執行緒B呼叫join方法,插隊。
      • 執行緒A進入主動等待狀態,變為waiting
      • 執行緒B執行完畢了以後,執行緒A變為runnable
    • 呼叫LockSupport.park方法。Java併發包中的鎖,都是基於LockSupport物件實現的。
      • 呼叫LockSupport.park(),執行緒會阻塞,從running變為waiting
      • 呼叫LockSupport.unpark(),執行緒被喚醒,從waiting變為runnable

1.2.4 runnable -> timed_waiting

  • 有五種情況會出發執行緒從runnable轉到timed_waiting
    • 呼叫帶超時引數的Thread.sleep(long millis)
    • 獲得synchronized執行緒,呼叫帶引數的OBject.wait(long deadline)方法
    • 呼叫帶引數的LockSupport.parkNanos(Object blocker, long deadline)
    • 呼叫帶超時引數的LocalSupport.parkUntil(long deadline)

1.2.5 runnable -> terminated

這是一個自動的過程,一個執行緒正常執行完畢以後,就會變成terminated

如果執行時,有異常丟擲,也會終止程序

或者呼叫interrupt方法,中斷執行緒。