CompletableFuture实现非阻塞流水线的核心是避免get()、轮询和等待,通过supplyAsync/runAsync启动异步源头,thenApply/thenCompose等编排串行逻辑,thenCombine/allOf/anyOf处理并行聚合,exceptionally/handle统一异常兜底。

CompletableFuture 实现非阻塞流水线,核心在于**不调用 get()、不轮询、不等待**,而是用函数式方法串联任务,让线程在任务提交后立刻释放,结果就绪时由线程池自动触发后续处理。
用 supplyAsync / runAsync 启动异步源头
这是整个流水线的起点,必须异步开启,且明确区分有无返回值:
-
要结果就用
supplyAsync:返回CompletableFuture<t></t>,后续可链式转换。例如查用户:supplyAsync(() -> userRepo.findById(id)) -
纯执行就用
runAsync:返回CompletableFuture<void></void>,适合发日志、清缓存等“火种型”操作,不能接thenApply这类取值方法 - 两者默认走
ForkJoinPool.commonPool(),生产环境务必传入自定义线程池(如 IO 密集型用Executors.newCachedThreadPool()),避免挤占 CPU 任务资源
用 thenApply / thenAccept / thenCompose 编排串行逻辑
这些方法本身不阻塞,只注册回调,任务完成即由线程池调度执行:
-
thenApply:同步转换结果,比如把用户对象转成 DTO,仍在同一线程执行(轻量计算适用) -
thenApplyAsync:异步转换,指定线程池,适合耗时处理(如渲染模板、加解密) -
thenCompose:关键!用于“前一个结果驱动下一个异步任务”,例如:f1.thenCompose(user -> supplyAsync(() -> orderService.listByUser(user))),它会扁平化嵌套的CompletableFuture<completablefuture>></completablefuture>,保持单层结构
用 thenCombine / allOf / anyOf 处理并行与聚合
打破串行依赖,让独立任务真正并发执行:
立即学习“Java免费学习笔记(深入)”;
-
thenCombine:两个独立异步任务都完成后合并结果,例如“查用户”和“查权限”并行发起,再一起组装视图:userFut.thenCombine(roleFut, (u, r) -> new Profile(u, r)) -
CompletableFuture.allOf(f1, f2, f3):等待全部完成,但不返回结果;如需汇总,得手动f1.join()等取值(注意:join 不抛检异常,更安全) -
CompletableFuture.anyOf(f1, f2, f3):谁先完成就用谁,适合降级场景(如主服务超时,切到备用接口)
用 exceptionally / handle 统一兜底异常
避免异常中断流水线,确保每一步都有响应:
-
exceptionally:只捕获上游异常,返回同类型 fallback 值,适合简单降级(如“查不到用户 → 返回 Guest”) -
handle:万能处理器,无论成功或失败都会进入,参数是(result, throwable),可统一打日志 + 返回默认对象,类型也可不同(如成功返回User,异常返回null或ErrorResponse) - 不要只靠
exceptionally记日志——它不处理正常路径,想全覆盖请配whenComplete或直接用handle


















