Java 沒有提供安全強制終止線程的機制 (早期 stop()/suspend() 已棄用,因破壞鎖一致性)。Thread.interrupt() 僅是發出中斷請求,將目標線程的中斷狀態標誌位置 true。被中斷線程必須主動檢查並響應,這是一種協作機制。
| 方法 | 類型 | 功能 | 影響中斷狀態 |
|---|---|---|---|
thread.interrupt() | 實例 | 發出中斷請求,設置標誌位;若線程阻塞於 sleep/wait/join,拋 InterruptedException 並清除標誌位 | 設置/清除 |
thread.isInterrupted() | 實例 | 查詢指定線程中斷狀態 | 不改變 |
Thread.interrupted() | 靜態 | 查詢當前線程中斷狀態 | 清除標誌位 (歸 false) |
public class ComputeTask implements Runnable {
@Override public void run() {
while (!Thread.currentThread().isInterrupted()) { // 或 Thread.interrupted() 消費標誌
// 執行計算單元
doHeavyComputation();
}
System.out.println("任務感知中斷,優雅退出");
}
}
// 主線程控制
Thread t = new Thread(new ComputeTask());
t.start();
// ... 3秒後請求取消
t.interrupt();
輸出:任務感知中斷,優雅退出。
當線程阻塞於 Thread.sleep()、Object.wait()、Thread.join()、BlockingQueue.take()、Selector.select() 等可中斷阻塞方法時,收到中斷請求會:
InterruptedException (受檢異常)。正確處理模式:
public class BlockingTask implements Runnable {
@Override public void run() {
try {
while (true) {
// 阻塞操作
Thread.sleep(1000); // 或 queue.take(), latch.await() 等
doWork();
}
} catch (InterruptedException e) {
// 1. 記錄日誌 / 執行清理
System.out.println("檢測到中斷,執行收尾工作...");
// 2. **關鍵:重新設置中斷標誌** 讓上層調用者知曉
Thread.currentThread().interrupt();
// 3. 返回/拋出,結束 run()
return;
}
}
}
public class InterruptDemo {
static class Worker extends Thread {
private final Thread target;
Worker(Thread target) { this.target = target; }
@Override public void run() {
while (true) {
System.out.println("Worker 運行中...");
sleep(2000);
target.interrupt(); // 主動中斷目標線程
}
}
void sleep(long ms) { try { Thread.sleep(ms); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }
}
public static void main(String[] args) {
Thread mainThread = Thread.currentThread();
new Worker(mainThread).start();
try {
mainThread.join(); // 主線程阻塞等待 Worker 結束 (實際不會結束)
} catch (InterruptedException e) {
System.out.println("主線程收到中斷,即將退出"); // Worker interrupt() 觸發
}
}
}
輸出:主線程收到中斷退出,Worker 仍在後台運行 (守護線程隨 JVM 退出)。
Thread.currentThread().interrupt() 恢復標誌,或拋出/轉換為 InterruptedException/RuntimeException 向上傳播。while (!Thread.currentThread().isInterrupted()) 清晰表達意圖。Cancellable 介面或繼承 FutureTask,統一取消語義。catch (Exception e) { log... } 吞掉 InterruptedException 是嚴重 Bug,導致線程無法被取消。ExecutorService.shutdownNow() 內部調用 interrupt(),Future.cancel(true) 同理,優於手動管理線程。中斷是 Java 併發取消的基石,**尊重中斷協議** 是編寫健壯多線程代碼的職業素養。