多線程並行計算時,主線程需要等待所有子線程完成並收集結果。傳統 Thread.join() + 共享變數方式繁瑣且線程不安全。Callable + Future 提供標準化異步計算模型。
| 介面 | 方法 | 返回值 | 拋出異常 | 用途 |
|---|---|---|---|---|
| Runnable | run() | void | 不可拋受檢異常 | 無返回值任務 |
| Callable<V> | call() | V | 可拋任意異常 | 有返回值任務 |
| Future<V> | get()/get(timeout) | V | InterruptedException, ExecutionException | 異步結果句柄 |
ExecutorService executor = Executors.newFixedThreadPool(10);
List> futures = new ArrayList<>();
// 1. 提交 100 個 Callable 任務
for (int i = 0; i < 100; i++) {
final int taskId = i;
Future future = executor.submit(new Callable() {
@Override public Integer call() throws Exception {
// 模擬耗時計算
Thread.sleep(ThreadLocalRandom.current().nextInt(100));
return taskId * 2; // 返回計算結果
}
});
futures.add(future);
}
// 2. 主線程收集所有結果(按提交順序阻塞)
List results = new ArrayList<>();
for (Future future : futures) {
try {
results.add(future.get()); // 阻塞直到完成
} catch (InterruptedException | ExecutionException e) {
log.error("任務失敗", e);
}
}
// 3. 聚合處理
int sum = results.stream().mapToInt(Integer::intValue).sum();
System.out.println("總和: " + sum);
executor.shutdown();
Java 8+ 推薦使用 CompletableFuture,支援非阻塞鏈式組合。
List> cfs = IntStream.range(0, 100)
.mapToObj(i -> CompletableFuture.supplyAsync(() -> {
sleep(random(100));
return i * 2;
}, executor))
.collect(toList());
// 等待全部完成,無需手動 get()
CompletableFuture all = CompletableFuture.allOf(cfs.toArray(new CompletableFuture[0]));
all.thenRun(() -> {
List results = cfs.stream()
.map(CompletableFuture::join) // 已完成,非阻塞
.collect(toList());
int sum = results.stream().mapToInt(Integer::intValue).sum();
System.out.println("異步聚合總和: " + sum);
}).join(); // 主線程等待聚合完成
CompletableFuture f1 = CompletableFuture.supplyAsync(() -> heavyCalc1(), executor);
CompletableFuture f2 = CompletableFuture.supplyAsync(() -> heavyCalc2(), executor);
// 兩個並行計算完成後,合併結果
CompletableFuture combined = f1.thenCombine(f2, (r1, r2) -> r1 + r2);
combined.thenAccept(sum -> System.out.println("組合結果: " + sum));
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
if (random() > 0.5) throw new RuntimeException("失敗");
return "成功";
}, executor).exceptionally(ex -> {
log.warn("降級處理", ex);
return "默認值";
});
| 工廠方法 | 適用場景 | 特點 |
|---|---|---|
| newFixedThreadPool(n) | 固定並發數,長期運行任務 | 隊列無界,可能 OOM |
| newCachedThreadPool() | 大量短生命任務 | 線程可回收,無界創建,風險大 |
| newSingleThreadExecutor() | 串行化執行 | 保證順序 |
| newWorkStealingPool() | CPU 密集型、分治任務 | ForkJoinPool,工作窺探 |
| 自定義 ThreadPoolExecutor | 生產環境 | 有界隊列、拒絕策略、監控指標 |
@Configuration
public class ThreadPoolConfig {
@Bean("taskExecutor")
public ThreadPoolExecutor taskExecutor() {
return new ThreadPoolExecutor(
10, 50, // core / max
60L, TimeUnit.SECONDS, // keepAlive
new LinkedBlockingQueue<>(1000), // 有界隊列
new ThreadFactoryBuilder().setNameFormat("biz-worker-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略:調用者執行
);
}
}
future.get() 拋出 ExecutionException 包裝真實異常,CompletableFuture.exceptionally() 定義降級邏輯。executor.shutdown() + awaitTermination(),防止任務丟失。