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 保證跨線程可見性;僅能在任務主動檢查點生效。
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():實例方法,檢查指定線程標誌不清除。
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()