CompletableFuture 比 Future 更好用,因为它支持非阻塞回调、函数式编排、多任务合并(allOf/anyOf)及灵活异常处理(handle/whenComplete),而 Future 仅支持阻塞等待或轮询。

CompletableFuture 为什么比 Future 更好用
因为 Future 只能阻塞等待结果或轮询状态,无法链式响应、组合多个异步任务、也无法处理异常传播;而 CompletableFuture 是可完成的(complete-able),支持函数式编排、非阻塞回调、多任务合并与错误恢复。
它本质是 Future 的增强实现,同时实现了 Future 和 CompletionStage 接口 —— 后者才是编排能力的来源。
如何用 supplyAsync + thenApply 编排简单异步流
这是最常用的“提交任务 → 转换结果”模式。注意:默认使用 ForkJoinPool.commonPool(),IO 密集型任务建议显式传入自定义线程池。
-
supplyAsync接收无参函数,返回CompletableFuture -
thenApply在前一个任务成功后同步执行转换,仍返回CompletableFuture - 若中间抛出异常,
thenApply不会执行,需用exceptionally或handle捕获
CompletableFuturefuture = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000); return "hello"; } catch (InterruptedException e) { throw new RuntimeException(e); } }).thenApply(s -> s.toUpperCase()).exceptionally(t -> "ERROR");
多个异步任务怎么合并:allOf vs anyOf
CompletableFuture.allOf 等待所有任务完成,但返回 CompletableFuture —— 它不聚合结果,必须手动 get 每个子 future;anyOf 返回第一个完成的结果(类型为 Object,需强转)。
立即学习“Java免费学习笔记(深入)”;
真正需要「结果聚合」时,得自己封装:比如用 allOf + thenApply 配合数组/列表收集。
-
allOf适合“全部就绪后统一触发后续动作”,如批量写入后发通知 -
anyOf适合“冗余调用取最快响应”,如多源查缓存 - 两者都不处理子任务异常:任一失败,
allOf仍完成但后续join()会抛异常;anyOf可能返回异常结果
CompletableFuturea = CompletableFuture.supplyAsync(() -> "A"); CompletableFuture b = CompletableFuture.supplyAsync(() -> "B"); CompletableFuture all = CompletableFuture.allOf(a, b); CompletableFuture > combined = all.thenApply(v -> Arrays.asList(a.join(), b.join()));
异常处理别只靠 exceptionally
exceptionally 只捕获上游的异常,且只能返回同类型结果;而 handle 同时接收结果和异常(任一为 null),更灵活;whenComplete 则不改变结果,只做副作用(如日志、清理)。
- 要用
handle做 fallback + 类型转换,比如把异常转成默认值 -
whenComplete内不能 throw 异常,否则会中断链路;handle可以 throw,由下游exceptionally接住 - 不要在回调里直接
get()或join(),会阻塞线程池线程,导致死锁或吞吐下降
最容易被忽略的是:异步回调的执行线程取决于前一个 stage 的完成方式 —— 如果前一个任务是同步 complete(比如用 complete() 手动设置),回调可能在调用线程中执行,而非线程池线程。这点对上下文(如 Spring 的 RequestScope)影响很大。











