CompletionStage接口
CompletionStage代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另外一个阶段。一个阶段的计算执行可以是一个Function,Consumer或者Runnable。一个阶段的执行可能是被单个阶段的完成触发,也可能是由多个阶段一起触发
CompletableFuture
JDK5新增了Future接口,用于描述一个异步计算的结果。虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和我们的异步编程的初衷相违背,轮询的方式又会耗费无谓的 CPU 资源,而且也不能及时地得到计算结果。
在Java8中,CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合 CompletableFuture 的方法。
它实现了Future和CompletionStage接口
CompletableFuture实现了Future接口的如下策略:
- CompletableFuture无法直接控制完成,所以cancel操作被视为是另一种异常完成形式。方法isCompletedExceptionally可以用来确定一个CompletableFuture是否以任何异常的方式完成。
- 以一个CompletionException为例,方法get()和get(long,TimeUnit)抛出一个ExecutionException,对应CompletionException。为了在大多数上下文中简化用法,这个类还定义了方法join()和getNow,而不是直接在这些情况中直接抛出CompletionException。
CompletableFuture实现了CompletionStage接口的如下策略:
- 为了完成当前的CompletableFuture接口或者其他完成方法的回调函数的线程,提供了非异步的完成操作。
- 没有显式入参Executor的所有async方法都使用ForkJoinPool.commonPool()为了简化监视、调试和跟踪,所有生成的异步任务都是标记接口AsynchronousCompletionTask的实例。
- 所有的CompletionStage方法都是独立于其他共有方法实现的,因此一个方法的行为不会受到子类中其他方法的覆盖。
CompletableFuture 提供了四个静态方法来创建一个异步操作。
方法 |
---|
CompletableFuture<Void> runAsync(Runnable runnable) |
CompletableFuture<Void> runAsync(Runnable runnable,Executor executor) |
supplyAsync(Supplier<U> supplier) |
<U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor) |
static void runAsync() throws ExecutionException, InterruptedException {
CompletableFuture future = CompletableFuture.runAsync(()->{
String value = "this is runAsync";
System.out.println(value);
});
Object o = future.get();
System.out.println(o);
}
static void supplyAsync() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
String value = "this is supplyAsync";
System.out.println(value);
return value;
});
String o = future.get();
System.out.println(o);
}
其中supplyAsync用于有返回值的任务,runAsync则用于没有返回值的任务。Executor参数可以手动指定线程池,否则默认ForkJoinPool.commonPool()系统级公共线程池
计算结果完成时的回调方法
当CompletableFuture的计算结果完成,或者抛出异常的时候,可以执行特定的Action。
方法 |
---|
public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action) |
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action) |
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor) |
public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn) |
static void whenComplete(){
CompletableFuture.supplyAsync(()->{
String value = "this is supplyAsync";
System.out.println(value);
return value;
}).whenComplete((s, throwable) -> {
System.out.println("this is accept");
System.out.println(s);
System.out.println(throwable);
});
}
static void exceptionally() throws ExecutionException, InterruptedException {
CompletableFuture future = CompletableFuture.supplyAsync(()->{
String value = "this is supplyAsync";
System.out.println(Integer.valueOf(value));
return value;
}).exceptionally(throwable -> {
System.out.println(throwable);
return "执行报错";
});
Object o = future.get();
System.out.println(o);
}
whenComplete 和 whenCompleteAsync 的区别:
whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。
thenApply 方法
当一个线程依赖另一个线程时,可以使用 thenApply 方法来把这两个线程串行化。
方法 |
---|
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn) |
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn) |
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor) |
handle 方法
handle 是执行任务完成时对结果的处理。handle 方法和 thenApply 方法处理方式基本一样。不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法。
方法 |
---|
public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn); |
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn); |
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Executor executor); |
thenAccept 消费处理结果
接收任务的处理结果,并消费处理,无返回结果。
方法 |
---|
public CompletionStage<Void> thenAccept(Consumer<? super T> action); |
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action); |
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor); |
thenRun 方法
跟 thenAccept 方法不一样的是,不关心任务的处理结果。只要上面的任务执行完成,就开始执行 thenAccept 。
方法 |
---|
public CompletionStage<Void> thenRun(Runnable action) |
public CompletionStage<Void> thenRunAsync(Runnable action) |
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor) |
thenCombine 合并任务
thenCombine 会把 两个 CompletionStage 的任务都执行完成后,把两个任务的结果一块交给 thenCombine 来处理。
方法 |
---|
public <U,V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn); |
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn); |
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor); |
thenAcceptBoth
当两个CompletionStage都执行完成后,把结果一块交给thenAcceptBoth来进行消耗
方法 |
---|
public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action) |
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action) |
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor) |
applyToEither 方法
两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的转化操作。
方法 |
---|
public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn) |
public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn) |
public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor) |
acceptEither 方法
两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的消耗操作。
方法 |
---|
public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action); |
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action); |
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor); |
runAfterEither 方法
两个CompletionStage,任何一个完成了都会执行下一步的操作(Runnable)
方法 |
---|
public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action); |
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action); |
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor); |
runAfterBoth
两个CompletionStage,都完成了计算才会执行下一步的操作(Runnable)
方法 |
---|
public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,Runnable action); |
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action); |
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor); |
thenCompose
thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作。
方法 |
---|
public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn); |
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) ; |
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn, Executor executor) ; |