Java 沒有 Thread.stop()(已棄用,不安全)。中斷是一種協作機制:發起方調用 interrupt() 設置標誌位,被中斷方主動檢查並決定如何響應(退出、清理、拋異常、忽略)。
| 方法 | 類型 | 作用 | 關鍵行為 |
|---|---|---|---|
thread.interrupt() | 實例 | 請求中斷 | 設置線程中斷狀態為 true;若線程阻塞在 sleep/wait/join,拋 InterruptedException 並清除中斷狀態 |
thread.isInterrupted() | 實例 | 查詢狀態 | 返回中斷狀態,**不清除** |
Thread.interrupted() | 靜態 | 查詢並清除 | 返回當前線程中斷狀態,**並清除為 false** |
while (!Thread.currentThread().isInterrupted()) {
// 執行計算任務
if (checkCondition()) doSomething();
}
// 退出循環後可選拋出異常或正常結束
主動輪詢 isInterrupted(),不拋異常,乾淨退出。
try {
while (true) {
TimeUnit.SECONDS.sleep(1); // 或 blockingQueue.take()
doPeriodicWork();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 重置中斷狀態!關鍵步驟
// 清理資源、記錄日誌
return; // 或 throw new RuntimeException(e)
}
鐵律:捕獲 InterruptedException 後必須重置中斷狀態(Thread.currentThread().interrupt()),否則上層調用者無法感知中斷請求。
synchronized 獲取鎖:不可中斷,只能用 Lock.lockInterruptibly();InputStream.read():不可中斷,需關閉 Socket/Stream 觸發異常;Channel / Selector:支持中斷,close() 會喚醒並拋 ClosedByInterruptException。
class PrimeGenerator extends Thread {
@Override public void run() {
long num = 1;
while (!isInterrupted()) { // 場景一:主動檢查
if (isPrime(num)) System.out.println("Prime: " + num);
num++;
}
System.out.println("PrimeGenerator 收到中斷,優雅退出");
}
private boolean isPrime(long n) {
if (n < 2) return false;
for (long i = 2; i * i <= n; i++) if (n % i == 0) return false;
return true;
}
}
public class InterruptDemo {
public static void main(String[] args) throws InterruptedException {
PrimeGenerator gen = new PrimeGenerator();
gen.start();
TimeUnit.SECONDS.sleep(5);
gen.interrupt(); // 發起中斷請求
gen.join(); // 等待線程實際結束
System.out.println("主線程結束");
}
}
ExecutorService pool = Executors.newFixedThreadPool(10);
Future> future = pool.submit(() -> {
while (!Thread.currentThread().isInterrupted()) { /* work */ }
});
// 取消任務
future.cancel(true); // true = mayInterruptIfRunning -> 調用 thread.interrupt()
// 關閉線程池
pool.shutdown(); // 拒絕新任務,等待現有任務完成
pool.shutdownNow(); // 嘗試中斷正在執行的任務,返回未執行任務列表
關鍵:future.cancel(true) 和 shutdownNow() 都依賴任務代碼正確響應中斷(檢查標誌或拋異常)。
| 錯誤代碼 | 後果 | 修正 |
|---|---|---|
catch (InterruptedException e) { log.error(e); } | 吞掉中斷,線程繼續跑,調用者以為已取消 | 捕獲後 Thread.currentThread().interrupt(); 重置狀態 |
while (true) { ... } // 無檢查 | 中斷請求被忽略,線程永不退出 | 循環條件加 !isInterrupted() |
Thread.interrupted() 用於實例線程檢查 | 誤清除當前線程(主線程)狀態,非目標線程 | 用 thread.isInterrupted() |
依賴 Thread.stop() / destroy() | 破壞鎖一致性,數據損壞,JDK 9+ 直接報錯 | 嚴禁使用,僅用中斷協作 |
thread.interrupt() / future.cancel(true) / executor.shutdownNow();InterruptedException / 輪詢 isInterrupted();Thread.currentThread().interrupt())、拋異常或正常返回。掌握中斷機制,是編寫可取消、可關閉、優雅降級併發程序的基石。