首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

Java 並發編程:任務終止的正確姿勢——狀態標誌、中斷機制與阻塞處理

     編輯:C++ 入門

方法一:volatile 布爾標誌(優雅終止)

public class ControlledTask implements Runnable {
    private volatile boolean cancelled = false;

    public void run() {
        while (!cancelled) {
            // 執行任務邏輯
        }
        // 清理資源
        System.out.println("Task stopped gracefully");
    }

    public void cancel() { cancelled = true; }

    public static void main(String[] args) throws InterruptedException {
        ControlledTask task = new ControlledTask();
        Thread t = new Thread(task);
        t.start();
        Thread.sleep(3000);
        task.cancel();  // 設置標誌,任務下次循環檢查時退出
    }
}

關鍵點:volatile 保證跨線程可見性;僅能在任務主動檢查點生效。

方法二:Thread.interrupt() 標準中斷機制

public class InterruptibleTask implements Runnable {
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                System.out.println("Working...");
                Thread.sleep(100);  // 可中斷阻塞
            } catch (InterruptedException e) {
                // sleep 中被中斷會拋出異常,中斷狀態被清除
                System.out.println("Interrupted during sleep");
                break;  // 或 return
            }
        }
        System.out.println("Task stopping");
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new InterruptibleTask());
        t.start();
        Thread.sleep(3000);
        t.interrupt();  // 設置中斷標誌,喚醒 sleep/wait
    }
}

阻塞情況下的中斷響應

阻塞類型interrupt() 效果處理方式
Thread.sleep() / Object.wait()拋出 InterruptedException,清除中斷標誌catch 異常後 break/return,或重新設置 Thread.currentThread().interrupt()
I/O 操作不拋異常,僅設置中斷標誌(Java NIO 可關閉 Channel 觸發異常)循環中檢查 isInterrupted() 或 interrupted()
鎖等待不拋異常,僅設置標誌改用 Lock.lockInterruptibly() 可拋異常響應

推薦檢查模式

while (!Thread.interrupted()) {  // 檢查並清除標誌
    try {
        // 可中斷操作
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();  // 重新設置,供上層感知
        break;
    }
}

Thread.interrupted():靜態方法,檢查當前線程中斷標誌並清除。
Thread.currentThread().isInterrupted():實例方法,檢查指定線程標誌不清除。

Executor 框架下的任務取消

ExecutorService exec = Executors.newFixedThreadPool(5);
List> futures = new ArrayList<>();
for (int i = 0; i < 10; ++i) {
    futures.add(exec.submit(() -> {
        while (!Thread.currentThread().isInterrupted()) { /* work */ }
    }));
}

// 取消所有任務
exec.shutdownNow();  // 向所有線程發送 interrupt()

// 單獨取消某任務
Future f = exec.submit(task);
f.cancel(true);  // true = mayInterruptIfRunning,發送 interrupt()

現代最佳實踐總結

  1. 優先使用 Executor + Future,避免直接操作 Thread。
  2. 任務代碼必須響應中斷:定期檢查 isInterrupted(),catch InterruptedException 後清理並退出。
  3. 不要吞噬中斷異常:catch 後至少重新設置標誌 Thread.currentThread().interrupt()。
  4. 長時間計算任務:在循環中插入 if (Thread.interrupted()) break;。
  5. I/O 任務:使用 NIO AsynchronousSocketChannel 或定期檢查標誌關閉流。
  6. 鎖等待:改用 ReentrantLock.lockInterruptibly() 替代 synchronized。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved