1.背景
編寫多線程相關的程序,必然會用到線程狀態的相關知識點,
那麼這篇博客就給大家系統的分析一下多線程的狀態,
由於java中線程狀態與操作系統中的線程狀態劃分有區別,
因此這裏優先介紹操作系統的5種線程狀態
2.操作系統給線程劃分的5種狀態
狀態說明:
狀態一:【初始狀態】僅是在語言層面創建了線程對象,還未與操作系統線程關聯
狀態二:【可運行狀態(就緒狀態)】指該線程已經被創建(與操作系統線程關聯),可以由 CPU 調度執行
狀態三:【運行狀態】指獲取了 CPU 時間片運行中的狀態當 CPU 時間片用完,會從【運行狀態】轉換至【可運行狀態】,會導致線程的上下文切換,因此並不是線程越多越好.
狀態四:【阻塞狀態】如果調用了阻塞 API,如 BIO 讀寫文件,這時該線程實際不會用到 CPU,會導致線程上下文切換,進入【阻塞狀態】等 BIO 操作完畢,會由操作系統喚醒阻塞的線程,轉換至【可運行狀態】與【可運行狀態】的區別是,對【阻塞狀態】的線程來說只要它們一直不喚醒,調度器就一直不會考慮調度它們
狀態五:【終止狀態】表示線程已經執行完畢,生命週期已經結束,不會再轉換爲其它狀態
3.java中給線程劃分的6中狀態
java中規定線程有6中狀態
源碼: Thread.State 中,如下:
public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED; }
狀態說明:
NEW: 線程剛被創建,但是還沒有調用 start() 方法
RUNNABLE:當調用了 start() 方法之後,注意,Java API 層面的 RUNNABLE 狀態涵蓋了 操作系統 層面的【可運行狀態】、【運行狀態】和【阻塞狀態】(由於 BIO 導致的線程阻塞,在 Java 裏無法區分,仍然認爲是可運行)
BLOCKED 、WAITING 、TIMED_WAITING : 都是 Java API 層面對【阻塞狀態】的細分,請看下面的狀態案例演示。
TERMINATED:當線程代碼運行結束
4.代碼演示java中的5種狀態
package com.ldp.demo01; import com.common.MyThreadUtil; import lombok.extern.slf4j.Slf4j; /** * @author 姿勢帝-博客園 * @address https://www.cnblogs.com/newAndHui/ * @WeChat 851298348 * @create 01/16 6:38 * @description */ @Slf4j public class ThreadStateTest { /** * java 中線程的6中狀態演示 * * @param args */ public static void main(String[] args) { // 演示 NEW 狀態 Thread thread1 = new Thread(() -> { }, "thread1"); // 演示 RUNNABLE 狀態 Thread thread2 = new Thread(() -> { while (true) { } }, "thread2"); thread2.start(); // 演示 TERMINATED 狀態 Thread thread3 = new Thread(() -> { log.debug("running........"); }, "thread3"); thread3.start(); // 演示 TIMED_WAITING 狀態 Thread thread4 = new Thread(() -> { synchronized (ThreadStateTest.class) { MyThreadUtil.sleep(10000); } }, "thread4"); thread4.start(); // 演示 WAITING 狀態 Thread thread5 = new Thread(() -> { try { thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } }, "thread5"); thread5.start(); // 演示 BLOCKED 狀態 Thread thread6 = new Thread(() -> { synchronized (ThreadStateTest.class) { MyThreadUtil.sleep(10000); } }, "thread6"); thread6.start(); // 等2秒 後查看狀態 MyThreadUtil.sleep(2); log.debug("thread1 state = {}", thread1.getState()); // NEW log.debug("thread2 state = {}", thread2.getState()); // RUNNABLE log.debug("thread3 state = {}", thread3.getState()); // TERMINATED log.debug("thread4 state = {}", thread4.getState()); // TIMED_WAITING log.debug("thread5 state = {}", thread5.getState()); // WAITING log.debug("thread6 state = {}", thread6.getState()); // BLOCKED } }
測試結果:
21:08:29 [thread3] DEBUG com.ldp.demo01.ThreadStateTest.33 -> running........
21:08:31 [main] DEBUG com.ldp.demo01.ThreadStateTest.65 -> thread1 state = NEW
21:08:31 [main] DEBUG com.ldp.demo01.ThreadStateTest.66 -> thread2 state = RUNNABLE
21:08:31 [main] DEBUG com.ldp.demo01.ThreadStateTest.67 -> thread3 state = TERMINATED
21:08:31 [main] DEBUG com.ldp.demo01.ThreadStateTest.68 -> thread4 state = TIMED_WAITING
21:08:31 [main] DEBUG com.ldp.demo01.ThreadStateTest.69 -> thread5 state = WAITING
21:08:31 [main] DEBUG com.ldp.demo01.ThreadStateTest.70 -> thread6 state = BLOCKED