CompletableFuture 是 Java 8 引入的一种用于处理异步编程的工具。它提供了一种非常灵活而且易于使用的方式来处理并发任务,能够简化代码的编写,并提高程序的性能。
CompletableFuture 类实现了 Future 和 CompletionStage 接口,因此可以用来表示一个异步计算的结果,还可以在计算完成后执行一些操作。下面将详细介绍 CompletableFuture 的使用和一些常见的应用场景。
一、基本用法
1、创建 CompletableFuture 对象
CompletableFuture 可以通过以下方式进行创建:
代码语言:javascript复制CompletableFuture<T> future = new CompletableFuture<>();
2、执行异步任务
可以使用线程池执行异步任务,并设置任务执行完毕后的回调函数:
代码语言:javascript复制CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// 异步任务的具体逻辑
}, executor);
这里的 executor 是一个可选的参数,可以指定线程池,如果不指定,则使用默认的 ForkJoinPool 线程池。
3、获取异步任务的结果
可以使用 get() 方法来获取异步任务的结果,注意这是一个阻塞方法,会一直等待任务完成:
代码语言:javascript复制T result = future.get();
4、处理任务的执行结果
可以使用 thenAccept()、thenApply()、thenRun() 等方法对任务的执行结果进行处理,这些方法都接受一个回调函数作为参数,任务完成后会触发回调函数的执行。
5、异常处理
可以使用 exceptionally() 方法来处理任务执行过程中出现的异常:
代码语言:javascript复制CompletableFuture<T> future = CompletableFuture.supplyAsync(() -> {
// 执行可能会抛出异常的代码
}).exceptionally(ex -> {
// 异常处理逻辑
return defaultValue;
});
二、组合多个 CompletableFuture
1、thenCompose()
通过 thenCompose() 方法可以将两个 CompletableFuture 对象串联起来,将一个任务的结果作为另一个任务的输入:
代码语言:javascript复制CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = future1.thenCompose(result -> CompletableFuture.supplyAsync(() -> result * 2));
这样,当 future1 完成时,它的结果会被传递给 future2 进行进一步处理。
2、thenCombine()
通过 thenCombine() 方法可以将两个 CompletableFuture 对象的结果进行合并处理:
代码语言:javascript复制CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 result2);
这里的回调函数接受 future1 和 future2 的结果,并返回它们的和。
3、allOf() 和 anyOf()
allOf() 方法接受一个 CompletableFuture 数组作为参数,等待所有的 CompletableFuture 都完成后返回:
代码语言:javascript复制CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
anyOf() 方法接受一个 CompletableFuture 数组作为参数,等待任意一个 CompletableFuture 完成后返回:
代码语言:javascript复制CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);
三、异常处理和超时
1、exceptionally()
通过 exceptionally() 方法可以处理任务执行过程中出现的异常,返回一个默认值或者进行其他的异常处理逻辑。
2、handle()
handle() 方法类似于 exceptionally(),但是可以处理任务正常完成后的结果和异常情况。
3、whenComplete()
whenComplete() 方法接收一个 BiConsumer 参数,在任务完成后无论是否出现异常都会被调用,可以对任务的结果进行处理。
4、timeout()
可以使用 completeOnTimeout() 或者 orTimeout() 方法来设置任务的超时时间。
四、并行流与 CompletableFuture
Java 8 还提供了并行流的功能,可以很方便地将一个集合的操作并行化。结合 CompletableFuture,我们可以更灵活地控制并行任务的执行顺序和流程。
五、应用场景
CompletableFuture 可以应用于很多场景,包括:
- 并发执行多个任务,并等待所有任务完成后进行下一步操作;
- 异步获取远程数据,提高系统性能;
- 将多个阻塞 IO 操作组合成一个异步任务;
- 异步调用外部服务或接口。
总结一下,CompletableFuture 提供了一种简洁而强大的方式来处理异步编程。通过组合多个 CompletableFuture 对象,可以实现复杂的任务流程和并发逻辑。它不仅提供了丰富的方法用于处理结果、处理异常和设置超时,还能与并行流相结合,进一步提高程序的性能。