一、Callable 与 Runnable 对比
| 特性 |
Runnable |
Callable<V> |
| 返回值 |
无(void) |
有(V 类型) |
| 异常处理 |
不能抛出 checked Exception |
可声明抛出 Exception |
| 函数式接口方法 |
run() |
call() |
| 适用场景 |
无需返回结果的异步任务 |
需要返回结果 / 异常处理的异步任务 |
二、Future 核心
1. 定义与作用
Future 是对异步任务执行结果的抽象,提供对任务的取消、状态查询、结果获取能力,是 Callable 的 "结果载体"。
2. 核心 API
| 方法 |
功能描述 |
异常说明 |
boolean cancel(boolean mayInterruptIfRunning) |
取消任务,参数指定是否中断运行中任务 |
- |
boolean isCancelled() |
判断任务是否在完成前被取消 |
- |
boolean isDone() |
判断任务是否完成(正常终止 / 异常 / 取消均返回 true) |
- |
V get() |
阻塞获取结果 |
InterruptedException(线程被中断)、ExecutionException(任务执行异常)、CancellationException(任务被取消) |
V get(long timeout, TimeUnit unit) |
超时阻塞获取结果 |
新增 TimeoutException(超时) |
3. FutureTask 实现
4. 应用场景:并行查询商品信息
- 问题:同步查询 5 个接口(各 50ms)需 250ms+
- 解决方案:用 Future 并行执行,总耗时≈最长接口耗时(50ms)
- 代码示例:见原文档
FutureTaskDemo2
5. 局限性
- 结果获取阻塞,无回调机制
- 无法链式调用多个任务
- 不能组合多个任务结果
- 缺乏异常处理机制
三、CompletableFuture 核心(Future 增强版)
1. 核心优势
- 实现 Future 接口,兼容原有功能
- 支持任务编排(串行 / 并行 / 聚合)
- 提供回调机制,非阻塞获取结果
- 内置异常处理
- 支持自定义线程池
2. 异步任务创建(4 个静态方法)
| 方法 |
特点 |
返回值 |
runAsync(Runnable) |
无返回值,默认线程池 |
CompletableFuture<Void> |
runAsync(Runnable, Executor) |
无返回值,自定义线程池 |
CompletableFuture<Void> |
supplyAsync(Supplier<U>) |
有返回值,默认线程池 |
CompletableFuture |
supplyAsync(Supplier<U>, Executor) |
有返回值,自定义线程池 |
CompletableFuture |
注意:默认线程池为ForkJoinPool.commonPool(),建议按业务自定义线程池避免线程饥饿
3. 结果获取方式
| 方法 |
异常处理 |
特点 |
get() |
checked 异常(需捕获 / 抛出) |
阻塞 |
join() |
unchecked 异常(无需强制捕获) |
阻塞 |
4. 核心功能分类
(1)结果处理(无返回新结果)
whenComplete(BiConsumer<T, Throwable>):处理正常结果 / 异常
exceptionally(Function<Throwable, T>):异常时返回默认值
- 示例:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
if (new Random().nextInt(10) % 2 == 0) {
throw new RuntimeException("测试异常");
}
return "成功";
});
future.whenComplete((result, ex) -> {
System.out.println("结果:" + result + ",异常:" + ex);
}).exceptionally(ex -> {
System.out.println("异常处理:" + ex.getMessage());
return "默认值";
});
(2)结果转换(返回新 CompletableFuture)
| 方法 |
作用 |
区别 |
thenApply(Function<T, U>) |
转换结果类型 |
同一 CompletableFuture 内转换 |
thenCompose(Function<T, CompletableFuture<U>>) |
依赖任务串联 |
生成新 CompletableFuture,避免嵌套 |
(3)结果消费(无返回值)
| 方法 |
作用 |
适用场景 |
thenAccept(Consumer<T>) |
消费单个结果 |
单任务结果处理 |
thenAcceptBoth(CompletableFuture<U>, BiConsumer<T, U>) |
消费两个任务结果 |
两个任务都完成后处理 |
thenRun(Runnable) |
不关心结果,执行动作 |
任务完成后触发后续操作 |
(4)任务组合
| 组合类型 |
方法 |
作用 |
| And 聚合 |
thenCombine(CompletableFuture<U>, BiFunction<T, U, V>) |
两个任务完成后合并结果 |
| And 聚合 |
runAfterBoth(CompletableFuture<?>, Runnable) |
两个任务完成后执行动作(无返回) |
| Or 聚合 |
applyToEither(CompletableFuture<T>, Function<T, U>) |
取先完成任务的结果并转换 |
| Or 聚合 |
acceptEither(CompletableFuture<T>, Consumer<T>) |
取先完成任务的结果并消费 |
| Or 聚合 |
runAfterEither(CompletableFuture<?>, Runnable) |
任意一个任务完成后执行动作 |
| 多任务 |
allOf(CompletableFuture<?>... cfs) |
等待所有任务完成(无返回值) |
| 多任务 |
anyOf(CompletableFuture<?>... cfs) |
等待任意一个任务完成(返回该任务结果) |
5. 经典案例:烧水泡茶(最优工序)
// 任务1:洗水壶->烧开水(无返回值)
CompletableFuture<Void> f1 = CompletableFuture.runAsync(() -> {
System.out.println("T1:洗水壶(1s)");
sleep(1);
System.out.println("T1:烧开水(15s)");
sleep(15);
});
// 任务2:洗茶壶->洗茶杯->拿茶叶(有返回值)
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
System.out.println("T2:洗茶壶(1s)");
sleep(1);
System.out.println("T2:洗茶杯(2s)");
sleep(2);
System.out.println("T2:拿茶叶(1s)");
sleep(1);
return "龙井";
});
// 任务3:两个任务完成后泡茶
CompletableFuture<String> f3 = f1.thenCombine(f2, (__, tea) -> {
System.out.println("T1:拿到茶叶" + tea + ",开始泡茶");
return "上茶:" + tea;
});
System.out.println(f3.join()); // 输出:上茶:龙井
四、关键类关系图


五、核心总结
- 技术演进:
Runnable(无返回无异常)→ Callable(有返回有异常)→ Future(结果管理)→ CompletableFuture(任务编排 + 回调)
- 核心选择:
- 简单无返回异步任务:Runnable
- 需返回结果 / 异常处理:Callable+Future
- 复杂任务依赖(串行 / 并行 / 聚合):CompletableFuture
- 使用注意事项:
- 避免使用 CompletableFuture 默认线程池,按业务自定义
- 优先使用 join () 而非 get () 简化异常处理
- 复杂任务编排优先使用 CompletableFuture 的回调机制,减少阻塞
所有评论(0)