Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

    • Java并发概述
    • 线程与进程
    • Thread类与线程生命周期
    • 线程创建与任务模型
    • 线程安全
    • synchronized关键字
    • volatile关键字
    • Java内存模型(JMM)
    • 线程间通信
    • 线程池
    • 并发工具类
    • 原子操作类Atomic
    • 并发锁
    • 并发容器
    • ConcurrentHashMap
    • BlockingQueue
    • CopyOnWriteArrayList
    • ThreadLocal
    • Fork/Join框架
    • ScheduledThreadPoolExecutor
    • CompletableFuture
      • 1. 基本创建
      • 2. 串行编排
      • 3. 并行组合
      • 4. 异常处理
      • 5. get 与 join
      • 6. 超时控制
      • 7. 线程池与上下文
      • 8. 常见坑
      • 9. 专家实践与边界
      • Tips 快问快答
    • 虚拟线程
    • 死锁活锁与线程问题排查
    • 并发编程最佳实践
  • Java IO

  • JVM

  • Java
  • Java并发
Wray
2026-06-24
目录

CompletableFuture

CompletableFuture 是 Java 8 引入的异步编排工具。它比传统 Future 更强,可以表达异步执行、串行转换、并行组合、异常处理和结果回调。

# 1. 基本创建

无返回值:

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    sendMessage();
});

有返回值:

CompletableFuture<User> future = CompletableFuture.supplyAsync(() -> {
    return queryUser();
});

建议传入自定义线程池:

CompletableFuture.supplyAsync(this::queryUser, executor);

否则默认使用公共 ForkJoinPool,阻塞任务可能影响其他异步任务。

# 2. 串行编排

转换结果:

CompletableFuture<String> nameFuture = userFuture.thenApply(User::getName);

消费结果:

userFuture.thenAccept(user -> log.info("user={}", user));

继续异步任务并扁平化:

CompletableFuture<Order> orderFuture = userFuture.thenCompose(user -> {
    return CompletableFuture.supplyAsync(() -> queryOrder(user.id()), executor);
});

thenApply 返回普通值,thenCompose 返回并展开另一个 CompletableFuture。

# 3. 并行组合

两个任务结果合并:

CompletableFuture<User> userFuture = queryUserAsync();
CompletableFuture<Account> accountFuture = queryAccountAsync();

CompletableFuture<UserView> viewFuture = userFuture.thenCombine(accountFuture, UserView::new);

等待全部完成:

CompletableFuture<Void> all = CompletableFuture.allOf(future1, future2, future3);
all.join();

任意一个完成:

CompletableFuture<Object> any = CompletableFuture.anyOf(future1, future2);

# 4. 异常处理

兜底返回:

CompletableFuture<User> future = queryUserAsync()
        .exceptionally(e -> defaultUser());

统一处理成功或失败:

future.handle((result, ex) -> {
    if (ex != null) {
        return fallback();
    }
    return result;
});

只观察:

future.whenComplete((result, ex) -> {
    if (ex != null) {
        log.error("执行失败", ex);
    }
});

区别:

方法 能否改变结果 场景
exceptionally 能 异常兜底
handle 能 成功失败都转换
whenComplete 通常不改变 记录日志、清理资源

# 5. get 与 join

方法 异常 是否受检
get ExecutionException 是
join CompletionException 否

生产代码不要无脑阻塞:

future.get(); // 可能长期等待

应设置超时或做异步链式处理。

# 6. 超时控制

future.orTimeout(1, TimeUnit.SECONDS);

超时返回默认值:

future.completeOnTimeout(defaultValue, 1, TimeUnit.SECONDS);

外部调用必须有超时,避免异步任务永久占用资源。

# 7. 线程池与上下文

带 Async 的方法如果不传线程池,可能使用默认公共池。

thenApply(...)
thenApplyAsync(...)

区别:

方法 执行线程
非 Async 可能在完成前一阶段的线程执行
Async 不传 executor 默认异步执行器
Async 传 executor 指定线程池执行

ThreadLocal 上下文不会自动传播,需要显式处理。

# 8. 常见坑

  • 默认线程池被阻塞任务占满。
  • 异常没有处理,链路悄悄失败。
  • allOf 后忘记收集各 Future 结果。
  • 在异步回调里阻塞等待另一个同池任务导致饥饿。
  • 没有超时控制。
  • ThreadLocal 上下文丢失。

# 9. 专家实践与边界

CompletableFuture 的核心价值是表达异步依赖关系,而不是把同步代码换个线程跑。优秀的异步编排应该能看出任务之间的依赖、并行、超时和失败策略。

queryUser ─┐
           ├─ thenCombine -> buildView -> fallback
queryOrder ┘
设计点 建议 风险
线程池 阻塞任务传自定义 executor 公共池被打满
超时 orTimeout / completeOnTimeout 永久等待
异常 exceptionally / handle 异步失败被忽略
上下文 显式传递 trace/user ThreadLocal 丢失
阻塞 避免同池内 join/get 线程池饥饿

复杂链路建议按业务阶段拆变量,不要写成一条难以调试的长链。每个外部调用都要有超时,每个聚合点都要考虑部分失败。

# Tips 快问快答

Q:CompletableFuture 比 Future 强在哪里? A:支持链式编排、组合、回调和异常处理。

Q:runAsync 和 supplyAsync 区别? A:前者无返回值,后者有返回值。

Q:thenApply 和 thenCompose 区别? A:thenApply 转换普通值,thenCompose 展开嵌套 Future。

Q:allOf 会返回所有结果吗? A:不会,只返回 CompletableFuture<Void>,结果要从各 Future 取。

Q:默认线程池能随便用吗? A:不建议,阻塞任务应传自定义线程池。

Q:join 和 get 区别? A:join 抛运行时异常,get 抛受检异常。

Q:异步任务需要超时吗? A:生产代码通常需要。

Q:ThreadLocal 会自动传到异步任务吗? A:不会,需要显式传递或包装任务。

上次更新: 2026/06/25, 14:19:18
ScheduledThreadPoolExecutor
虚拟线程

← ScheduledThreadPoolExecutor 虚拟线程→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式