當線程執行複雜算法或遞歸調用時,簡單的 interrupt() 可能無法及時響應。Java 提供 InterruptedException 機制,讓線程在檢測到中斷請求時主動拋出異常,從而實現可控中止。
模擬一個線程遞歸遍歷目錄查找指定文件,主線程 10 秒後發起中斷。
package com.diguage.books.concurrencycookbook.chapter1.recipe4;
import java.io.File;
public class FileSearch implements Runnable {
private String initPath;
private String fileName;
public FileSearch(String initPath, String fileName) {
this.initPath = initPath;
this.fileName = fileName;
}
@Override
public void run() {
File file = new File(initPath);
if (file.isDirectory()) {
try {
directoryProcess(file);
} catch (InterruptedException e) {
System.out.printf("%s: The search has been interrupted%n",
Thread.currentThread().getName());
}
}
}
private void directoryProcess(File file) throws InterruptedException {
File[] list = file.listFiles();
if (list != null) {
for (File f : list) {
if (f.isDirectory()) {
directoryProcess(f); // 遞歸處理子目錄
} else {
fileProcess(f); // 處理文件
}
}
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
private void fileProcess(File file) throws InterruptedException {
if (file.getName().equals(fileName)) {
System.out.printf("%s : %s%n",
Thread.currentThread().getName(),
file.getAbsolutePath());
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
}
package com.diguage.books.concurrencycookbook.chapter1.recipe4;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
FileSearch searcher = new FileSearch("C:\\", "autoexec.bat");
Thread thread = new Thread(searcher);
thread.start();
try {
TimeUnit.SECONDS.sleep(10); // 運行 10 秒
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt(); // 發起中斷請求
}
}
Thread-0 : C:\autoexec.bat
Thread-0: The search has been interrupted
輸出顯示:線程找到目標文件後打印路徑,隨後檢測到中斷標誌,拋出 InterruptedException,在 run() 方法捕獲並打印中斷信息,線程優雅退出。
Thread.interrupted(),及時拋出異常。run() 方法捕獲異常,執行清理邏輯後結束。thread.interrupt() 設置中斷標誌,不強制殺死線程。本例改編自《Java 7 Concurrency Cookbook》。InterruptedException 也是 Java 並發 API(如 sleep()、wait())的標準中斷響應方式。