public class CompletableFuture implements Future, CompletionStage
根据其实现的接口可知,它有两个特点:
- Future,表示异步执行的结果
- CompletionStage,表示整个异步计算的一个阶段,它能被其它的stage触发,也能触发其它的stage。CompletionStage的组合可以分为3种(假设有3个CompletionStage,分别为1、2、3):
- then,关系为 2依赖于1、3依赖于2,则1、2、3顺序执行
- both,关系为 3依赖于1、3依赖于2,则1、2都执行完后,3再执行
- either,关系为 3依赖于1、3依赖于2,则1、2只要有一个执行完后,3就执行
根据上面的依赖关系,所以CompletionStage的方法也分为3类,方法名中有combine、both的方法表示both关系,方法名中有either的方法表示either关系,其余的就是then关系
volatile Object result;
表示异步执行的结果,当result为null,表示该阶段还未执行完成,当result为AltResult且AltResult的Throwable ex
不为null,表示该阶段执行异常,其它则为执行成功
1.1 构造CompletableFuture
new CompletableFutur()
public static CompletableFuture runAsync(Runnable runnable)
public static CompletableFuture runAsync(Runnable runnable, Executor executor)
public static CompletableFuture supplyAsync(Supplier supplier)
public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)
下面的4个方法会被直接提交并执行,Supplier
是有返回值的,Runnable
没有返回值
1.2 获取执行结果
public T get() throws InterruptedException, ExecutionException
public T join()
阻塞式的获取任务结果,并不推荐这么做,因为会阻塞调用线程,从异步变成同步了,那跟Future
没什么区别了,需要使用回调函数来处理
1.3 触发回调函数
public boolean complete(T value)
public boolean completeExceptionally(Throwable ex)
还有其它的一些以complete开头的方法,最常用的就是上面2种,它会将result从null变为指定值,然后触发依赖任务的执行
1.4 设置回调函数
一个回调函数对应一个CompletableFuture
1.4.1 then关系
// 没有返回值
public CompletableFuture thenRun(
Runnable action)
public CompletableFuture thenRunAsync(
Runnable action)
public CompletableFuture thenRunAsync(
Runnable action, Executor executor)
// 没有返回值
public CompletionStage thenAccept(Consumer super T> action);
public CompletionStage thenAcceptAsync(Consumer super T> action);
public CompletionStage thenAcceptAsync(Consumer super T> action,
Executor executor);
// 有返回值
public CompletableFuture thenApply(
Function super T,? extends U> fn)
public CompletableFuture thenApplyAsync(
Function super T,? extends U> fn)
public CompletableFuture thenApplyAsync(
Function super T,? extends U> fn, Executor executor)
// 有返回值
public CompletableFuture thenCompose(
Function super T, ? extends CompletionStage> fn)
public CompletableFuture thenComposeAsync(
Function super T, ? extends CompletionStage> fn)
public CompletableFuture thenComposeAsync(
Function super T, ? extends CompletionStage> fn, Executor executor)
这些方法都是实现的CompletionStage
中定义的方法,他描述的是一种串行的关系
- 假设用户创建了CompletableFuture1,然后调用了2次thenApply方法,则上图描述了最后的依赖关系,即当CompletableFuture1完成后,则先触发函数2的执行,再触发则先触发函数1的执行,是一种栈的结构,此时获取最后结果要从CompletableFuture2中获取
1.4.2 both关系
除了串行的关系,CompletionStage
中还定义了描述AND
关系的方法
// 有返回值
public CompletableFuture thenCombine(
CompletionStage extends U> other,
BiFunction super T,? super U,? extends V> fn)
public CompletableFuture thenCombineAsync(
CompletionStage extends U> other,
BiFunction super T,? super U,? extends V> fn)
public CompletableFuture thenCombineAsync(
CompletionStage extends U> other,
BiFunction super T,? super U,? extends V> fn, Executor executor)
// 无返回值
public CompletableFuture thenAcceptBoth(
CompletionStage extends U> other,
BiConsumer super T, ? super U> action)
public CompletableFuture thenAcceptBothAsync(
CompletionStage extends U> other,
BiConsumer super T, ? super U> action)
public CompletableFuture thenAcceptBothAsync(
CompletionStage extends U> other,
BiConsumer super T, ? super U> action, Executor executor)
// 无返回值
public CompletableFuture runAfterBoth(CompletionStage> other,
Runnable action)
public CompletableFuture runAfterBothAsync(CompletionStage> other,
Runnable action)
public CompletableFuture runAfterBothAsync(CompletionStage> other,
Runnable action, Executor executor)
上面的方法都表示当调用者future
与other
执行完成后,才会执行传入的函数。
1.4.3 either关系
CompletionStage
中还定义了描述OR
关系的方法
// 有返回值
public CompletableFuture applyToEither(
CompletionStage extends T> other, Function super T, U> fn)
public CompletableFuture applyToEitherAsync(
CompletionStage extends T> other, Function super T, U> fn)
public CompletableFuture applyToEitherAsync(
CompletionStage extends T> other, Function super T, U> fn,
Executor executor)
// 无返回值
public CompletableFuture acceptEither(
CompletionStage extends T> other, Consumer super T> action)
public CompletableFuture acceptEitherAsync(
CompletionStage extends T> other, Consumer super T> action)
public CompletableFuture acceptEitherAsync(
CompletionStage extends T> other, Consumer super T> action,
Executor executor)
// 无返回值
public CompletableFuture runAfterEither(CompletionStage> other,
Runnable action)
public CompletableFuture runAfterEitherAsync(CompletionStage> other,
Runnable action)
public CompletableFuture runAfterEitherAsync(CompletionStage> other,
Runnable action, Executor executor)
上面的方法都表示当调用者future
与other
任意一个执行完成后,才会执行传入的函数。
1.5 异常处理
下面的方法用来做异常处理,如果把回调函数比作try中的代码块,那么这个方法就是catch中的代码块
public CompletableFuture exceptionally(
Function fn) {
return uniExceptionallyStage(fn);
}
1.6 finally功能
下面的方法可以用来做收尾工作,相当于finally中的代码块,一定会被执行;当被依赖的任务报错,后续依赖任务的函数不会执行(除exceptionally),只是将对应的CompletableFuture的result被设为AltResult(被依赖任务的异常)
public CompletableFuture whenComplete(
BiConsumer super T, ? super Throwable> action)
public CompletableFuture whenCompleteAsync(
BiConsumer super T, ? super Throwable> action)
public CompletableFuture whenCompleteAsync(
BiConsumer super T, ? super Throwable> action, Executor executor)
public CompletableFuture handle(
BiFunction super T, Throwable, ? extends U> fn)
public CompletableFuture handleAsync(
BiFunction super T, Throwable, ? extends U> fn)
public CompletableFuture handleAsync(
BiFunction super T, Throwable, ? extends U> fn, Executor executor)
1.7 执行线程
- 所有方法名中带有Async的方法,如果不指定executor,则使用默认线程池
ForkJoinPool#commonPool()
,线程个数为核数(可通过-Djava.util.concurrent.ForkJoinPool.common.parallelism指定),但是如果线程个数小于2,则不使用,而是每一个函数或任务都会创建一个线程 - 如果使用不带Async的方法,则会在设置了值(比如调用了complete、completeExceptionally)的线程中执行任务
- 建议,对于执行时间可能较长的函数或任务,比如远程的RPC,尽量使用async + 指定
Executor
的方式,因为设置了Executor
,则提交的任务在指定的线程池中运行,这样做的好处- 对于使用默认线程池,避免默认的线程池中有慢任务执行使线程耗尽,导致新提交的任务积压而无法快速执行
- 对于使用不带Async的方法,避免影响调用线程中的代码执行