Java 執行緒生命週期
了解執行緒的生命週期有助於正確管理執行緒和除錯多執行緒程式。
執行緒狀態
Java 執行緒有以下六種狀態(定義在 Thread.State 列舉):
NEW → RUNNABLE ⇄ BLOCKED/WAITING/TIMED_WAITING → TERMINATED
| 狀態 | 說明 |
|---|---|
| NEW | 已建立但尚未啟動 |
| RUNNABLE | 正在執行或準備執行 |
| BLOCKED | 等待取得鎖 |
| WAITING | 無限期等待 |
| TIMED_WAITING | 有時限的等待 |
| TERMINATED | 執行完畢 |
NEW 狀態
建立執行緒但尚未呼叫 start():
Thread thread = new Thread(() -> {
System.out.println("執行中");
});
System.out.println(thread.getState()); // NEW
RUNNABLE 狀態
執行緒正在執行或等待 CPU 排程:
Thread thread = new Thread(() -> {
while (true) {
// 執行中
}
});
thread.start();
System.out.println(thread.getState()); // RUNNABLE
注意:RUNNABLE 包含 Ready(等待 CPU)和 Running(正在執行)兩個子狀態
BLOCKED 狀態
等待取得同步鎖:
Object lock = new Object();
Thread t1 = new Thread(() -> {
synchronized (lock) {
try {
Thread.sleep(10000); // 持有鎖 10 秒
} catch (InterruptedException e) {}
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) { // 等待取得鎖
System.out.println("取得鎖");
}
});
t1.start();
Thread.sleep(100); // 確保 t1 先取得鎖
t2.start();
Thread.sleep(100);
System.out.println(t2.getState()); // BLOCKED
WAITING 狀態
無限期等待,需要其他執行緒喚醒:
Object.wait()
Object lock = new Object();
Thread thread = new Thread(() -> {
synchronized (lock) {
try {
lock.wait(); // 等待被 notify
} catch (InterruptedException e) {}
}
});
thread.start();
Thread.sleep(100);
System.out.println(thread.getState()); // WAITING
// 喚醒
synchronized (lock) {
lock.notify();
}
Thread.join()
Thread t1 = new Thread(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {}
});
Thread t2 = new Thread(() -> {
try {
t1.join(); // 等待 t1 完成
} catch (InterruptedException e) {}
});
t1.start();
t2.start();
Thread.sleep(100);
System.out.println(t2.getState()); // WAITING
LockSupport.park()
Thread thread = new Thread(() -> {
LockSupport.park(); // 等待 unpark
});
thread.start();
Thread.sleep(100);
System.out.println(thread.getState()); // WAITING
LockSupport.unpark(thread); // 喚醒
TIMED_WAITING 狀態
有時限的等待:
Thread.sleep()
Thread thread = new Thread(() -> {
try {
Thread.sleep(5000); // 睡眠 5 秒
} catch (InterruptedException e) {}
});
thread.start();
Thread.sleep(100);
System.out.println(thread.getState()); // TIMED_WAITING
Object.wait(timeout)
Object lock = new Object();
Thread thread = new Thread(() -> {
synchronized (lock) {
try {
lock.wait(5000); // 最多等待 5 秒
} catch (InterruptedException e) {}
}
});
thread.start();
Thread.sleep(100);
System.out.println(thread.getState()); // TIMED_WAITING
Thread.join(timeout)
Thread t1 = new Thread(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {}
});
Thread t2 = new Thread(() -> {
try {
t1.join(5000); // 最多等待 5 秒
} catch (InterruptedException e) {}
});
t1.start();
t2.start();
Thread.sleep(100);
System.out.println(t2.getState()); // TIMED_WAITING
TERMINATED 狀態
執行緒執行完畢:
Thread thread = new Thread(() -> {
System.out.println("執行完畢");
});
thread.start();
thread.join(); // 等待完成
System.out.println(thread.getState()); // TERMINATED
狀態轉換
┌──────────────────────────────────────┐
│ │
▼ │
┌─────┐ ┌──────────┐ ┌────────────────────┐ │
│ NEW │ ──▶ │ RUNNABLE │ ──▶ │ TERMINATED │ │
└─────┘ └──────────┘ └────────────────────┘ │
│ │
│ synchronized │
▼ │
┌─────────┐ │
│ BLOCKED │ ─────────────────────────────────┘
└─────────┘ 取得鎖
│
│ wait/join/park
▼
┌─────────┐
│ WAITING │ ─────────────────────────────────┐
└─────────┘ notify/中斷 │
│ │
│ sleep/wait(t)/join(t) │
▼ │
┌───────────────────┐ │
│ TIMED_WAITING │ ────────────────────────────┘
└───────────────────┘ 超時/notify/中斷
轉換方式
| 起始狀態 | 目標狀態 | 方式 |
|---|---|---|
| NEW | RUNNABLE | start() |
| RUNNABLE | BLOCKED | 等待 synchronized |
| BLOCKED | RUNNABLE | 取得鎖 |
| RUNNABLE | WAITING | wait(), join(), park() |
| WAITING | RUNNABLE | notify(), join 完成, unpark() |
| RUNNABLE | TIMED_WAITING | sleep(t), wait(t), join(t) |
| TIMED_WAITING | RUNNABLE | 超時或被喚醒 |
| RUNNABLE | TERMINATED | run() 完成或例外 |
監控執行緒狀態
取得狀態
Thread thread = Thread.currentThread();
Thread.State state = thread.getState();
System.out.println("目前狀態:" + state);
取得所有執行緒
// 取得所有執行緒
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread t : threads) {
System.out.println(t.getName() + ": " + t.getState());
}
使用 JMX
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// 取得執行緒資訊
long[] threadIds = threadMXBean.getAllThreadIds();
ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadIds);
for (ThreadInfo info : threadInfos) {
System.out.println(info.getThreadName() + ": " + info.getThreadState());
}
// 檢測死鎖
long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
if (deadlockedThreads != null) {
System.out.println("發現死鎖!");
}
中斷機制
中斷執行緒
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
// 執行任務
}
System.out.println("收到中斷,結束執行");
});
thread.start();
Thread.sleep(1000);
thread.interrupt(); // 送出中斷
處理 InterruptedException
Thread thread = new Thread(() -> {
try {
while (true) {
Thread.sleep(1000); // 可中斷
// 執行任務
}
} catch (InterruptedException e) {
// 處理中斷
System.out.println("被中斷");
// 重新設定中斷狀態(如果需要上層處理)
Thread.currentThread().interrupt();
}
});
thread.start();
thread.interrupt();
中斷對不同狀態的影響
| 狀態 | 中斷效果 |
|---|---|
| RUNNABLE | 設定中斷標誌 |
| BLOCKED | 設定中斷標誌 |
| WAITING | 拋出 InterruptedException |
| TIMED_WAITING | 拋出 InterruptedException |
實際範例
監控執行緒
public class ThreadMonitor {
public static void printThreadStates() {
Map<Thread.State, Integer> stateCount = new EnumMap<>(Thread.State.class);
for (Thread t : Thread.getAllStackTraces().keySet()) {
stateCount.merge(t.getState(), 1, Integer::sum);
}
System.out.println("執行緒狀態統計:");
stateCount.forEach((state, count) ->
System.out.println(state + ": " + count));
}
}
等待執行緒完成
public void waitForThreads(List<Thread> threads, long timeout)
throws InterruptedException {
long deadline = System.currentTimeMillis() + timeout;
for (Thread t : threads) {
long remaining = deadline - System.currentTimeMillis();
if (remaining <= 0) {
throw new TimeoutException("等待超時");
}
t.join(remaining);
}
}
重點整理
| 狀態 | 進入方式 | 離開方式 |
|---|---|---|
| NEW | new Thread() | start() |
| RUNNABLE | start()、被喚醒 | 完成、等待 |
| BLOCKED | synchronized | 取得鎖 |
| WAITING | wait()、join() | notify()、完成 |
| TIMED_WAITING | sleep(t)、wait(t) | 超時、被喚醒 |
| TERMINATED | run() 完成 | - |
- 使用
getState()取得執行緒狀態 - 使用
interrupt()中斷等待中的執行緒 - WAITING 和 BLOCKED 的區別:WAITING 是主動等待,BLOCKED 是被動等待鎖
- 正確處理
InterruptedException