参考:
CompletableFuture是java 8引入的,用于Java异步编程。异步编程是一种通过在与主应用程序线程不同的线程上运行任务并通知主线程其进度,完成或失败的方法来编写非阻塞代码的方法。
这样,您的主线程就不会阻塞/等待任务完成,并且可以并行执行其他任务。具有这种并行性可以大大提高程序的性能。
Future
Future被用作异步计算结果的参考。它提供了一个isDone()方法来检查计算是否完成,以及一个get()方法来检索计算完成后的结果。
Future VS CompletableFuture:
1.手动完成
Future提供了一个isDone()方法来检查计算是否完成,以及get()方法来检索计算结果。但是,Future不提供手动完成的方法。CompletableFuture的complete()方法可帮助我们手动完成Future
/**
* Manual Completion 手动完成
*/
private static void manualCompletion() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "1111";
});
executorService.submit(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//手动结束核心
future.complete("手动完成");
});
System.out.println(future.get());
executorService.shutdown();
}
因为Future的get()方法在完成计算的之前是阻塞的,我们可以使用complete()方法来手动完成计算。
2.多个Future组成调用链
/**
* 调用链
*/
public static void callbackChain() throws ExecutionException, InterruptedException {
CompletableFuture completableFuture
= CompletableFuture
.supplyAsync(() -> "Knolders!")
.thenRun(() -> System.out.println("Example with thenRun()."));
System.out.println(completableFuture.get());
}
3.组合多个CompletableFuture结果
如果是Future,则无法创建异步工作流程,即长时间运行的计算。但是CompletableFuture为我们提供了方法来实现此功能:
/**
* 组合
*/
private static void thenCompose() {
CompletableFuture<String> completableFuture =
CompletableFuture.supplyAsync(() -> "Hello")
.thenCompose(value ->
CompletableFuture.supplyAsync(
() -> value + " Knolders! Its thenCompose"));
completableFuture.thenAccept(System.out::println); // Hello Knolders! Its thenCompose
}
如果你希望合并要并行运行的100种不同的Future,然后在所有这些Future完成后再运行某些功能。可是使用如下方法:
/**
* 组合所有的结果
*/
private static void allOf() throws ExecutionException, InterruptedException {
CompletableFuture<String> completableFuture1
= CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> completableFuture2
= CompletableFuture.supplyAsync(() -> "lv!");
CompletableFuture<String> completableFuture3
= CompletableFuture.supplyAsync(() -> "Its allOf");
/*
这个方法并不直接返回结果只是返回一个CompletableFuture
*/
CompletableFuture<Void> combinedFuture
= CompletableFuture.allOf(completableFuture1, completableFuture2, completableFuture3);
System.out.println(combinedFuture.get()); //输出null
assert (completableFuture1.isDone());
assert (completableFuture2.isDone());
assert (completableFuture3.isDone());
//使用以下两种方法获取最终结果
CompletableFuture<List<String>> listCompletableFuture = combinedFuture.thenApply(v ->
Stream.of(completableFuture1, completableFuture2, completableFuture3).
map(CompletableFuture::join).
collect(Collectors.toList()));
System.out.println(listCompletableFuture.get());
String combined = Stream.of(completableFuture1, completableFuture2, completableFuture3)
.map(CompletableFuture::join)
.collect(Collectors.joining(" "));
System.out.println(combined);
}
4.异常处理
如果发生异常,调用链将会停止调用。
private static void exception() {
Integer age = -1;
CompletableFuture<String> exceptionFuture = CompletableFuture.supplyAsync(() -> {
if (age < 0) {
throw new IllegalArgumentException("Age can not be negative");
}
if (age > 18) {
return "Adult";
} else {
return "Child";
}
}).exceptionally(ex -> {
System.out.println("Oops! We have an exception - " + ex.getMessage());
return "Unknown!";
});
exceptionFuture.thenAccept(System.out::println); //Unknown!
}
private static void exceptionUsingHandle() {
Integer age = -1;
CompletableFuture<String> exceptionFuture = CompletableFuture.supplyAsync(() -> {
if (age < 0) {
throw new IllegalArgumentException("Age can not be negative");
}
if (age > 18) {
return "Adult";
} else {
return "Child";
}
}).handle((result, ex) -> {
if (ex != null) {
System.out.println("Oops! We have an exception - " + ex.getMessage());
return "Unknown!";
}
return result;
});
exceptionFuture.thenAccept(System.out::println); // Unknown!
}
网友评论