CompletableFuture
是 Java 中用于异步编程的工具,提供了丰富的方法来处理异步任务。下面解析一些CompletableFuture
的常用方法:
runAsync
和 supplyAsync
runAsync
: 用于执行没有返回值的异步任务。
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// 异步任务的逻辑
});
supplyAsync
: 用于执行有返回值的异步任务。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 异步任务的逻辑
return "Result";
});
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));
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);
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");
allOf
和 anyOf
allOf
: 等待所有给定的 CompletableFuture
完成。
CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2, future3);
anyOf
: 等待任意一个给定的 CompletableFuture
完成。
CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2, future3);
join
和 get
join
: 获取异步任务的结果,没有抛出检查异常。
String result = CompletableFuture.supplyAsync(() -> "Hello").join();
get
: 获取异步任务的结果,可能抛出 ExecutionException
和 InterruptedException
。
String result = CompletableFuture.supplyAsync(() -> "Hello").get();
这些方法提供了丰富的功能,让你能够更灵活地处理异步任务的执行结果、异常和组合。在实际应用中,根据具体场景和需求选择合适的方法组合使用,能够编写出高效、健壮且易读的异步代码。
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());
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());
cancel
和 isCancelled
cancel
: 取消异步任务的执行。
boolean cancelled = future.cancel(true);
isCancelled
: 判断异步任务是否被取消。
boolean isCancelled = future.isCancelled();
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
并行下载多个图片,可以通过类似的方式处理其他异步任务。这种方式能够提高系统的性能和响应速度。