首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 線程終止正確姿勢:volatile 標誌位 vs interrupt() 機制深度對比

     編輯:Java 相關知識

已棄用:Thread.stop()

暴力終止,導致鎖釋放不確定、對象損壞、數據不一致。嚴禁使用。

方案一:volatile boolean 標誌位 (推薦常規業務)


public class Worker implements Runnable {
    private volatile boolean running = true; // 保證可見性

    public void shutdown() { running = false; }

    @Override
    public void run() {
        while (running) {
            // 1. 執行任務單元
            doTask();
            // 2. 可選:檢查標誌位 (長任務中插入檢查點)
        }
        cleanup(); // 釋放資源
    }
}

優點:簡單、可控、線程自然退出 run() 執行 finally 塊釋放資源。
缺點:無法中斷阻塞操作 (sleep/wait/join/IO/鎖)。

方案二:Thread.interrupt() (中斷阻塞/協作式)


public class InterruptibleWorker implements Runnable {
    @Override
    public void run() {
        try {
            while (!Thread.currentThread().isInterrupted()) { // 檢查中斷狀態
                // 非阻塞任務
                doTask();
                // 或調用可中斷阻塞方法
                Thread.sleep(1000); // 會拋 InterruptedException
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // 重置標誌 (良好習慣)
        } finally {
            cleanup();
        }
    }
}

// 外部調用
workerThread.interrupt(); // 設置中斷標誌

中斷機制核心規則

場景interrupt() 效果中斷狀態
線程運行中 (非阻塞)僅設置標誌位true (需自行檢查 isInterrupted())
線程阻塞於 sleep/wait/join拋出 InterruptedException自動清除 (為 false)
線程阻塞於 IO (Channel)關閉 Channel,拋 ClosedByInterruptExceptiontrue
線程阻塞於 Lock.lock()不響應 (ReentrantLock 不可中斷)false
線程阻塞於 Lock.lockInterruptibly()拋 InterruptedException清除

最佳實踐組合模式


public class RobustWorker implements Runnable {
    private volatile boolean shutdown = false; // 業務級標誌

    @Override
    public void run() {
        try {
            while (!shutdown && !Thread.currentThread().isInterrupted()) {
                // 1. 可中斷阻塞操作優先
                blockingQueue.take(); // 可中斷
                // 2. 非阻塞任務 + 定期檢查
                processBatch();
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // 傳遞中斷
        } finally {
            // 3. 統一清理
            releaseResources();
        }
    }

    public void stop() {
        shutdown = true;        // 業務標誌
        thread.interrupt();     // 打破阻塞
    }
}

總結選型

  • 純計算/短任務循環 → volatile boolean 即可。
  • 涉及阻塞調用 (隊列、睡眠、NIO) → 必須配合 interrupt()。
  • 庫/框架代碼 → 拋出 InterruptedException 向上傳遞,不吞噬。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved