在Java中,線程的生命周期由六種主要狀態構成,每種狀態都有其特定的轉換條件。以下是Java線程的生命周期狀態及其轉換條件:
線程狀態
-
新建(NEW):
- 線程對象已經創建,但尚未調用
start()
方法。
Thread thread = new Thread();
- 線程對象已經創建,但尚未調用
-
就緒(RUNNABLE):
- 線程已調用
start()
方法,等待被線程調度器選中以便運行。需要注意的是,在某些文檔中,這個狀態也被稱為“可運行(RUNNABLE)”,包括實際運行狀態。
thread.start();
- 線程已調用
-
運行(RUNNING):
- 線程調度器從就緒線程池中選中該線程,并開始執行
run()
方法中的代碼。
- 線程調度器從就緒線程池中選中該線程,并開始執行
-
阻塞(BLOCKED):
- 線程在等待獲取一個監視器鎖,以便進入同步塊/方法。如果線程在同步代碼塊/方法中等待鎖,它就是阻塞狀態。
synchronized (lock) {// 線程進入同步塊 }
-
等待(WAITING):
- 線程等待另一線程顯式地喚醒。進入這種狀態有幾種方法:調用
Object.wait()
、Thread.join()
、或LockSupport.park()
,并且沒有設置超時時間。
synchronized (lock) {lock.wait(); // 必須在 synchronized 塊內調用 }
- 線程等待另一線程顯式地喚醒。進入這種狀態有幾種方法:調用
-
超時等待(TIMED_WAITING):
- 線程等待一定時間之后會自動喚醒。進入這種狀態的幾種方法包括:
Thread.sleep(long millis)
、Object.wait(long timeout)
、Thread.join(long millis)
、LockSupport.parkNanos()
、和LockSupport.parkUntil()
。
Thread.sleep(1000); // 休眠 1 秒
- 線程等待一定時間之后會自動喚醒。進入這種狀態的幾種方法包括:
-
終止(TERMINATED):
- 線程已執行完畢或由于異常退出,線程結束生命周期。
狀態轉換
線程在其生命周期中會在不同狀態之間進行轉換,主要的轉換條件如下:
-
新建 -> 就緒:
- 調用
start()
方法。
Thread thread = new Thread(); thread.start();
- 調用
-
就緒 -> 運行:
- 線程調度器選擇該線程進行執行。
-
運行 -> 阻塞:
- 線程嘗試獲取同步鎖,但鎖被其他線程持有。
synchronized (lock) {// 線程進入阻塞狀態等待鎖 }
-
運行 -> 等待:
- 線程調用
Object.wait()
方法或Thread.join()
方法,沒有設置超時。
synchronized (lock) {lock.wait(); }
- 線程調用
-
運行 -> 超時等待:
- 線程調用
Thread.sleep(long millis)
方法、Object.wait(long timeout)
方法、或Thread.join(long millis)
方法,并設置了超時。
Thread.sleep(1000);
- 線程調用
-
等待 -> 就緒:
- 其他線程調用
Object.notify()
或Object.notifyAll()
方法。
synchronized (lock) {lock.notify(); }
- 其他線程調用
-
超時等待 -> 就緒:
- 超時時間到。
// 等待時間到后自動進入就緒狀態
-
阻塞 -> 就緒:
- 線程獲得鎖。
synchronized (lock) {// 獲得鎖,進入就緒狀態 }
-
運行 -> 終止:
- 線程執行完成或拋出未捕獲的異常。
public void run() {// 執行完畢或拋出異常,線程終止 }
示例代碼
以下是一個簡單的示例代碼,演示了線程在不同狀態之間的轉換:
public class ThreadLifecycleDemo {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {try {System.out.println("Thread State: " + Thread.currentThread().getState()); // RUNNABLEThread.sleep(1000);synchronized (ThreadLifecycleDemo.class) {ThreadLifecycleDemo.class.wait();}} catch (InterruptedException e) {e.printStackTrace();}});System.out.println("Thread State after creation: " + thread.getState()); // NEWthread.start();System.out.println("Thread State after start: " + thread.getState()); // RUNNABLEThread.sleep(500);System.out.println("Thread State while sleeping: " + thread.getState()); // TIMED_WAITINGsynchronized (ThreadLifecycleDemo.class) {ThreadLifecycleDemo.class.notify();}Thread.sleep(500);System.out.println("Thread State after notify: " + thread.getState()); // TERMINATED}
}
在上述示例中,通過打印線程的狀態,可以觀察到線程在其生命周期中的狀態變化。了解這些狀態和轉換條件對于編寫并發程序和調試多線程問題非常重要。