CompletableFuture实现异步编排的核心是组合任务依赖与执行顺序,支持串行(thenApply/thenAccept/thenRun)、并行(allOf/anyOf)、异常处理(exceptionally/handle/whenComplete)及自定义线程池与超时控制。

Java 中用 CompletableFuture 实现异步编排,核心是组合多个异步任务的执行顺序与依赖关系,比如“先执行 A,再用 A 的结果执行 B”,或“并行执行 C 和 D,等两者都完成后再汇总”。它比原始 Future 更灵活,支持链式调用、异常处理、超时控制和多任务协调。
串行编排:用 thenApply / thenAccept / thenRun 传递结果
适合有明确先后依赖的任务。前一个任务完成,自动触发后一个任务,并可传递结果或仅执行副作用。
-
thenApply:接收上一阶段结果,返回新结果(用于转换) -
thenAccept:接收结果但不返回值(用于消费,如打印、存库) -
thenRun:不接收结果,只执行动作(类似 finally 块)
示例:
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> "hello");
CompletableFuture<Integer> taskB = taskA.thenApply(s -> s.length());
CompletableFuture<Void> taskC = taskB.thenAccept(len -> System.out.println("长度:" + len));
并行执行与聚合:用 allOf / anyOf 协调多个任务
allOf 等待所有任务完成(不合并结果),anyOf 等第一个完成即返回。注意它们返回的是 CompletableFuture<Void> 或 CompletableFuture<Object>,需手动获取各任务结果。
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 用
allOf+ 数组遍历 +join()汇总结果 - 用
anyOf适合“竞速”场景,如调用多个备份接口取最快响应
示例(allOf 汇总):
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "a");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "b");
CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> "c");
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3);
String[] results = all.thenApply(v -> new String[]{f1.join(), f2.join(), f3.join()}).join();
异常处理与回退:用 exceptionally / handle / whenComplete
异步链中出错不会自动中断,需显式捕获。三者区别在于:
-
exceptionally:只在异常时执行,返回替代结果(类似 try-catch 的 catch) -
handle:无论成功失败都执行,可统一处理并返回新结果 -
whenComplete:只做副作用(如清理资源),不改变结果或异常
示例:
CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> {
if (Math.random() > 0.5) throw new RuntimeException("失败");
return "success";
}).exceptionally(ex -> "默认值");
自定义线程池与超时控制
避免阻塞公共 ForkJoinPool,默认的 supplyAsync 使用共享池。生产环境建议传入专用线程池;超时可用 orTimeout(JDK 9+)或结合 completeOnTimeout 实现。
- 指定线程池:
supplyAsync(() -> ..., executor) - 超时回退:
future.orTimeout(3, TimeUnit.SECONDS).exceptionally(...) - 兼容低版本 JDK:
CompletableFuture.delayedExecutor(3, SECONDS).thenRunAsync(() -> future.complete("timeout"))(需配合手动控制)

















