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

Java 並發基礎實戰:優雅退出任務(二)— Future.cancel 與中斷機制深度應用

     編輯:Java 相關知識

Future 模式回顧

Future 結合 Proxy + Thread-Per-Message:獨立線程執行耗時任務,Future 物件持有任務引用,未來取得結果。

1. 手工 Future 實現(教學用)

class FileScannerTask implements Runnable {
    private File root; List paths = new ArrayList<>();
    FileScannerTask(File r) { this.root = r; }
    public void run() { traverse(root); }
    private void traverse(File f) {
        paths.add(f.getAbsolutePath());
        if (f.isDirectory()) for (File c : f.listFiles()) traverse(c);
    }
    List getSnapshot() { return new ArrayList<>(paths); }
}
class FileScannerFuture {
    private final FileScannerTask task;
    FileScannerFuture(FileScannerTask t) { this.task = t; new Thread(t).start(); }
    List getResult() { return task.getSnapshot(); }
}

缺點:無法判斷任務是否完成、無法取消、無異常傳播。

2. JDK 並發包 FutureTask 完整實現

class FileScannerTask implements Callable> {
    private final File root; private final List paths = new ArrayList<>();
    FileScannerTask(File r) { this.root = r; }
    public List call() { traverse(root); return paths; }
    private void traverse(File f) {
        if (Thread.currentThread().isInterrupted()) return; // 響應中斷
        paths.add(f.getAbsolutePath());
        if (f.isDirectory()) for (File c : f.listFiles()) traverse(c);
    }
    List getPartial() { return new ArrayList<>(paths); }
}

3. 使用 ExecutorService + Future

ExecutorService es = Executors.newCachedThreadPool();
Future> future = es.submit(new FileScannerTask(new File("C:")));

// 正常獲取(阻塞至完成)
List result = future.get();

// 超時取消
try { future.get(1, TimeUnit.SECONDS); }
catch (TimeoutException e) { future.cancel(true); } // true = mayInterruptIfRunning
finally { es.shutdown(); }

4. 異步取消與部分結果獲取

ExecutorService es = Executors.newCachedThreadPool();
FileScannerTask task = new FileScannerTask(new File("C:"));
Future> future = es.submit(task);

// 另一線程 1 秒後取消
new Thread(() -> { sleep(1); future.cancel(true); }).start();

try {
    List r = future.get();
} catch (CancellationException e) {
    List partial = task.getPartial(); // 取得已掃描路徑
    System.out.println("部分結果: " + partial.size());
} finally { es.shutdown(); }

關鍵點總結

  • future.cancel(true) 本質是對執行線程調用 interrupt()。
  • 任務必須主動檢查中斷狀態(Thread.interrupted() 或捕獲 InterruptedException)並快速返回,取消才生效。
  • Callable 配合 Future.get() 可獲得異常傳播與完成狀態檢查(isDone()/isCancelled())。
  • 取消後可透過任務物件本身(而非 Future)獲取部分結果快照。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved