让我来对比一下 CompletableFuture 和传统的 Future 接口的区别:
1. 基本功能对比
Future 接口的局限性:
// 传统Future的使用方式
ExecutorService executor = Executors.newFixedThreadPool(10);
Future<String> future = executor.submit(() -> {
Thread.sleep(1000);
return "结果";
});
// 获取结果 - 会阻塞
String result = future.get(); // 阻塞等待
CompletableFuture 的优势:
// CompletableFuture的使用方式
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
return "结果";
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
// 非阻塞方式处理结果
future.thenAccept(result -> {
System.out.println("处理结果: " + result);
});
2. 主要区别
-
异步结果处理
- Future:只能通过阻塞的
get()
方法获取结果 - CompletableFuture:支持回调方式处理结果,不会阻塞
- Future:只能通过阻塞的
-
任务组合
- Future:不支持任务组合
- CompletableFuture:支持多个任务的组合
// 组合两个任务 CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "任务1"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "任务2"); // 等待两个任务都完成 CompletableFuture<String> combined = future1.thenCombine(future2, (r1, r2) -> r1 + r2);
-
异常处理
- Future:异常会被包装在 ExecutionException 中
- CompletableFuture:提供专门的异常处理方法
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { if (true) throw new RuntimeException("错误"); return "结果"; }).exceptionally(throwable -> "发生错误: " + throwable.getMessage());
-
链式调用
- Future:不支持链式调用
- CompletableFuture:支持链式调用
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "原始数据") .thenApply(s -> s + " -> 处理1") .thenApply(s -> s + " -> 处理2") .thenAccept(System.out::println);
3. 实际应用场景对比
让我用代码展示一个实际场景的对比:
使用 Future:
ExecutorService executor = Executors.newFixedThreadPool(10);
// 提交第一个任务
Future<String> future1 = executor.submit(() -> {
Thread.sleep(1000);
return "任务1结果";
});
// 提交第二个任务
Future<String> future2 = executor.submit(() -> {
Thread.sleep(1500);
return "任务2结果";
});
// 获取结果 - 需要手动等待
String result1 = future1.get();
String result2 = future2.get();
String finalResult = result1 + " + " + result2;
使用 CompletableFuture:
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
return "任务1结果";
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1500);
return "任务2结果";
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
// 自动组合结果
CompletableFuture<String> finalResult = future1.thenCombine(future2,
(r1, r2) -> r1 + " + " + r2);
4. CompletableFuture 的优势总结
-
更灵活的异步处理
- 支持非阻塞的结果处理
- 提供丰富的回调方法
-
更强大的功能
- 支持任务组合
- 支持链式调用
- 提供更好的异常处理机制
-
更好的代码可读性
- 链式调用使代码更清晰
- 异步处理逻辑更直观
-
更丰富的 API
- 提供多种组合方法(thenCombine, allOf, anyOf 等)
- 支持超时处理
- 支持取消操作
-
更好的异常处理
- 专门的异常处理方法
- 可以在链式调用中处理异常
总的来说,CompletableFuture 是对 Future 接口的增强,它解决了 Future 的许多局限性,提供了更强大、更灵活的异步编程能力。CompletableFuture 是jdk中处理异步操作的首选工具。