Future 結合 Proxy + Thread-Per-Message:獨立線程執行耗時任務,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(); }
}
缺點:無法判斷任務是否完成、無法取消、無異常傳播。
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); } }
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(); }
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())。