深入理解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进行投诉反馈,一经查实,立即删除!