使用 CompletableFuture 实现异步编程
在现代 Java 开发中,异步编程是一项重要技能。而 CompletableFuture
是从 Java 8 开始提供的一个功能强大的工具,用于简化异步任务的编写和组合。本文将详细介绍 CompletableFuture
的基本使用和一些常见的应用场景。
1. 为什么选择 CompletableFuture?
传统的异步编程通常依赖于回调或 Future
,但这些方法存在一些缺陷:
- 回调地狱:嵌套层级多,代码难以阅读。
- Future 的
get()
方法是阻塞的,无法真正实现非阻塞式编程。
CompletableFuture
的优势在于:
- 支持非阻塞操作。
- 提供丰富的 API 用于任务的组合和处理。
- 更好的错误处理机制。
2. 基本用法
创建一个 CompletableFuture
import java.util.concurrent.CompletableFuture;public class CompletableFutureExample {public static void main(String[] args) {// 创建一个异步任务CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1000); // 模拟耗时操作} catch (InterruptedException e) {throw new RuntimeException(e);}return "Hello, CompletableFuture!";});// 非阻塞地获取结果future.thenAccept(result -> System.out.println("Result: " + result));System.out.println("Main thread is not blocked");// 防止主线程退出过早try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}
}
输出
Main thread is not blocked
Result: Hello, CompletableFuture!
3. 任务组合
thenApply: 转换结果
thenApply
方法用于将异步任务的结果转换为另一种类型。
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> "42").thenApply(Integer::parseInt).thenApply(num -> num * 2);future.thenAccept(result -> System.out.println("Final Result: " + result));
thenCompose: 链式调用
thenCompose
用于在一个任务完成后启动另一个异步任务。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello").thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World!"));future.thenAccept(System.out::println);
thenCombine: 合并两个任务
thenCombine
用于合并两个独立的异步任务的结果。
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");CompletableFuture<String> result = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
result.thenAccept(System.out::println);
4. 异常处理
在异步任务中,异常处理非常重要。CompletableFuture
提供了多种方法来优雅地处理异常。
exceptionally: 捕获异常并返回默认值
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {if (true) {throw new RuntimeException("Something went wrong");}return "Success";
}).exceptionally(ex -> {System.out.println("Exception: " + ex.getMessage());return "Default Value";
});future.thenAccept(System.out::println);
handle: 处理结果和异常
handle
方法无论任务成功还是失败都会执行,并可以访问异常信息。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {if (true) {throw new RuntimeException("Error occurred");}return "Success";
}).handle((result, ex) -> {if (ex != null) {System.out.println("Exception: " + ex.getMessage());return "Recovered from error";}return result;
});future.thenAccept(System.out::println);
5. 实际应用场景
并发请求处理
在需要同时处理多个请求时,可以利用 allOf
或 anyOf
方法。
allOf: 等待所有任务完成
CompletableFuture<Void> allTasks = CompletableFuture.allOf(CompletableFuture.runAsync(() -> System.out.println("Task 1")),CompletableFuture.runAsync(() -> System.out.println("Task 2")),CompletableFuture.runAsync(() -> System.out.println("Task 3"))
);allTasks.thenRun(() -> System.out.println("All tasks completed"));
anyOf: 任意任务完成即返回
CompletableFuture<Object> anyTask = CompletableFuture.anyOf(CompletableFuture.supplyAsync(() -> "Task 1 completed"),CompletableFuture.supplyAsync(() -> "Task 2 completed")
);anyTask.thenAccept(result -> System.out.println("First completed: " + result));
6. 总结
CompletableFuture
是 Java 异步编程的强大工具,提供了丰富的 API 来实现任务的创建、组合和异常处理。通过熟练掌握 CompletableFuture
,可以编写更加简洁高效的异步代码。
希望本文能帮助你更好地理解和使用 CompletableFuture
!
欢迎关注gzh:加瓦点灯
每天推送干货知识
本文由mdnice多平台发布