Java 中無安全的強制停止線程 API(stop()、suspend()、resume() 均已棄用)。本文系統總結三種標準停止方式,並通過實驗驗證各種場景下的行為差異。
volatile boolean 變量,線程定期檢查並主動退出。thread.interrupt(),線程通過 isInterrupted() 或捕獲 InterruptedException 響應。run() 方法。| 方法 | 作用對象 | 清除中斷標誌 | 適用場景 |
|---|---|---|---|
Thread.interrupted() |
當前線程 | 是 | 靜態工具方法,通常用於內部邏輯判斷 |
thread.isInterrupted() |
指定線程 | 否 | 外部監控線程狀態,推薦使用 |
thread.interrupt() |
指定線程 | 設置標誌為 true | 請求線程停止 |
public class Worker extends Thread {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) { // 推薦使用實例方法
// 業務邏輯
System.out.println("Working... " + System.currentTimeMillis());
}
System.out.println("線程正常退出");
}
}
// 測試
Worker w = new Worker();
w.start();
Thread.sleep(2000);
w.interrupt(); // 請求停止
阻塞方法會拋出 InterruptedException 並清除中斷標誌,需捕獲異常後重新設置標誌或直接退出:
@Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000); // 可能拋出 InterruptedException
}
} catch (InterruptedException e) {
// 方案A:重新設置中斷標誌供上層調用者感知
Thread.currentThread().interrupt();
// 方案B:直接退出(常見於獨立線程)
System.out.println("檢測到中斷,退出運行");
}
}
傳統阻塞 I/O 不響應中斷,需:
socket.close())觸發異常退出InterruptibleChannelreturn 而非異常控制流while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("收到停止信號,return 退出");
return; // 乾淨退出 run()
}
// 業務處理
}
stop() 暴力終止ThreadDeath(Error 子類),通常不被捕獲需要停止線程
│
├─ 能否修改線程代碼?
│ ├─ 是 → 採用中斷模式(interrupt + isInterrupted/InterruptedException)
│ └─ 否(第三方庫/不可控代碼)
│ ├─ 線程是否在阻塞 I/O?
│ │ ├─ 是 → 關閉底層資源(Socket/Channel/InputStream)
│ │ └─ 否 → 僅能依賴線程自然結束或進程級隔離
│ └─ 考慮未來重構為可中斷設計
InterruptedException 友好處理ExecutorService 管理線程生命周期,調用 shutdown()/shutdownNow()Thread.currentThread().isInterrupted()InterruptedException 後:重新設置中斷標誌 或 封裝為業務異常拋出catch (InterruptedException e) {})