深入理解Java CompletableFuture的使用
深入理解Java CompletableFuture的使用
解析:
CompletableFuture 是 Java 中用于异步编程的工具,提供了丰富的方法来处理异步任务。下面解析一些CompletableFuture的常用方法:
1. runAsync 和 supplyAsync
-
runAsync: 用于执行没有返回值的异步任务。CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { // 异步任务的逻辑 }); -
supplyAsync: 用于执行有返回值的异步任务。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // 异步任务的逻辑 return "Result"; });
2. thenApply 和 thenAccept
-
thenApply: 对异步任务的结果进行转换,返回一个新的CompletableFuture。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenApply(s -> s + " World"); -
thenAccept: 对异步任务的结果进行消费,没有返回值。CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello") .thenAccept(s -> System.out.println("Result: " + s));
3. thenCompose 和 thenCombine
-
thenCompose: 组合两个异步任务,返回一个新的CompletableFuture。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World")); -
thenCombine: 组合两个异步任务的结果,返回一个新的CompletableFuture。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenCombine(CompletableFuture.supplyAsync(() -> " World"), (s1, s2) -> s1 + s2);
4. exceptionally 和 handle
-
exceptionally: 处理异步任务的异常情况,返回一个默认值。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // 异步任务的逻辑,可能抛出异常 throw new RuntimeException("Error"); }).exceptionally(ex -> "Default Value"); -
handle: 处理异步任务的结果和异常,返回一个新的CompletableFuture。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // 异步任务的逻辑,可能抛出异常 throw new RuntimeException("Error"); }).handle((result, ex) -> result != null ? result : "Default Value");
5. allOf 和 anyOf
-
allOf: 等待所有给定的CompletableFuture完成。CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2, future3); -
anyOf: 等待任意一个给定的CompletableFuture完成。CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2, future3);
6. join 和 get
-
join: 获取异步任务的结果,没有抛出检查异常。String result = CompletableFuture.supplyAsync(() -> "Hello").join(); -
get: 获取异步任务的结果,可能抛出ExecutionException和InterruptedException。String result = CompletableFuture.supplyAsync(() -> "Hello").get();
这些方法提供了丰富的功能,让你能够更灵活地处理异步任务的执行结果、异常和组合。在实际应用中,根据具体场景和需求选择合适的方法组合使用,能够编写出高效、健壮且易读的异步代码。
7. thenRun 和 thenRunAsync
-
thenRun: 在异步任务完成后执行一个没有输入参数且没有返回值的操作。CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello") .thenRun(() -> System.out.println("Async task completed.")); -
thenRunAsync: 在异步任务完成后执行一个没有输入参数且没有返回值的操作,可以指定执行的线程池。CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello") .thenRunAsync(() -> System.out.println("Async task completed."), Executors.newCachedThreadPool());
8. thenCombineAsync 和 thenAcceptBothAsync
-
thenCombineAsync: 组合两个异步任务的结果,并使用指定的Executor执行。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenCombineAsync(CompletableFuture.supplyAsync(() -> " World"), (s1, s2) -> s1 + s2, Executors.newCachedThreadPool()); -
thenAcceptBothAsync: 组合两个异步任务的结果,并在两个任务都完成后执行一个消费者操作。CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello") .thenAcceptBothAsync(CompletableFuture.supplyAsync(() -> " World"), (s1, s2) -> System.out.println(s1 + s2), Executors.newCachedThreadPool());
9. cancel 和 isCancelled
-
cancel: 取消异步任务的执行。boolean cancelled = future.cancel(true); -
isCancelled: 判断异步任务是否被取消。boolean isCancelled = future.isCancelled();
10. thenComposeAsync 和 thenAcceptAsync
-
thenComposeAsync: 类似于thenCompose,用于组合两个异步任务,但可以指定执行的线程池。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenComposeAsync(s -> CompletableFuture.supplyAsync(() -> s + " World"), Executors.newCachedThreadPool()); -
thenAcceptAsync: 类似于thenAccept,对异步任务的结果进行消费,可以指定执行的线程池。CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello") .thenAcceptAsync(s -> System.out.println("Result: " + s), Executors.newCachedThreadPool());
这些方法提供了更多的灵活性和控制,允许你在处理异步任务时更精细地指定操作和执行环境。在实际开发中,根据具体需求选择合适的方法进行组合,可以更好地应对不同的异步编程场景。
举例:
下面我们将通过一个例子详细解释CompletableFuture的使用,并使用博客格式输出。
示例:并行下载图片
假设我们有一个需求:从多个网站并行下载图片,并在所有图片下载完成后进行一些处理。以下是使用CompletableFuture实现的示例代码。
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class ImageDownloader {
// 模拟图片下载
private static byte[] downloadImage(String imageUrl) {
// 实际的图片下载逻辑
System.out.println("Downloading image from " + imageUrl);
// 返回一个假设的图片字节数组
return new byte[]{1, 2, 3, 4, 5};
}
// 模拟图片处理
private static void processImage(byte[] imageBytes) {
// 实际的图片处理逻辑
System.out.println("Processing image: " + Arrays.toString(imageBytes));
}
public static void main(String[] args) {
List<String> imageUrls = Arrays.asList(
"https://example.com/image1.jpg",
"https://example.com/image2.jpg",
"https://example.com/image3.jpg"
);
try {
// 使用CompletableFuture并行下载图片
CompletableFuture<Void> allOf = CompletableFuture.allOf(
imageUrls.stream()
.map(url -> CompletableFuture.supplyAsync(() -> downloadImage(url))
.thenAcceptAsync(ImageDownloader::processImage))
.toArray(CompletableFuture[]::new)
);
// 等待所有图片下载完成
allOf.get();
// 所有图片下载完成后的处理
System.out.println("All images downloaded and processed successfully!");
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
解析与说明:
-
downloadImage方法:
private static byte[] downloadImage(String imageUrl) { // 实际的图片下载逻辑 System.out.println("Downloading image from " + imageUrl); // 返回一个假设的图片字节数组 return new byte[]{1, 2, 3, 4, 5}; }downloadImage方法模拟从指定URL下载图片的逻辑。 -
processImage方法:
private static void processImage(byte[] imageBytes) { // 实际的图片处理逻辑 System.out.println("Processing image: " + Arrays.toString(imageBytes)); }processImage方法模拟对下载的图片进行处理的逻辑。 -
使用CompletableFuture并行下载图片:
CompletableFuture<Void> allOf = CompletableFuture.allOf( imageUrls.stream() .map(url -> CompletableFuture.supplyAsync(() -> downloadImage(url)) .thenAcceptAsync(ImageDownloader::processImage)) .toArray(CompletableFuture[]::new) );通过
CompletableFuture.allOf方法,将所有图片的下载任务组合在一起,以便在所有图片下载完成后执行后续的操作。 -
等待所有图片下载完成:
allOf.get();通过
allOf.get()等待所有的图片下载任务完成。在实际应用中,可以根据需要添加超时等逻辑。 -
所有图片下载完成后的处理:
System.out.println("All images downloaded and processed successfully!");所有图片下载完成后,输出提示信息。
这个示例展示了如何使用CompletableFuture并行下载多个图片,可以通过类似的方式处理其他异步任务。这种方式能够提高系统的性能和响应速度。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!