CompletableFuture接口说明
CompletableFuture是Future的子类,接口Future接口虽然实现了异步调用,但是存在一个问题,为了判断线程是否已完成计算,或者要获取计算结果,我们需要不断的轮询,通过循环调用Future的isDone方法或者是直接调用get的方法阻塞线程。
在JDK8中,提供了CompletableFuture类来解决这类问题,它可以在线程完成计算后用when、then等方式调用我们定义后续处理方法,省去了轮询的操作(笔者最近在读RocketMQ源码,发现在Broker上使用了CompletableFuture类,因此打算记录一下基本功能和用法,希望后续有时间能详细研读一下实现源码。)
CompletableFuture有以下几种构造方式:
//没有计算过程,直接返回计算结果
CompletableFuture<String>futureNoComplete=CompletableFuture.completedFuture("hello world");
//没有返回值的异步计算
CompletableFuture<Void>futureNoReturnNoExecutor=CompletableFuture.runAsync(()->doSomething());
CompletableFuture<Void>futureNoReturnWithExecutor=CompletableFuture.runAsync(()->doSomething(), Executors.newSingleThreadExecutor());
//带返回值的异步计算
CompletableFuture<String> futureWithReturnNoExector=CompletableFuture.supplyAsync(()->doSomethingReturnString());
CompletableFuture<String> futureWithReturnWithExecutor=CompletableFuture.supplyAsync(()->doSomethingReturnString(), Executors.newSingleThreadExecutor());
当completeFuture代表的任务完成了,可以使用一系列的函数接口来定义当前Future完成后的后续计算。
//执行完当前任务后,以当前任务的返回值作为fn任务的输入,并返回计算结果
public <U> CompletableFuture<U> thenApply(
Function<? super T,? extends U> fn) {
return uniApplyStage(null, fn);
}
//执行完当前任务后,将返回值作为输入,计算fn任务,并返回结果
public <U> CompletableFuture<U> thenApplyAsync(
Function<? super T,? extends U> fn) {
return uniApplyStage(asyncPool, fn);
}
//执行完当前任务后,以当前任务返回值作为输入,并返回计算结果,该计算过程使用executor中的不同线程来执行
public <U> CompletableFuture<U> thenApplyAsync(
Function<? super T,? extends U> fn, Executor executor) {
return uniApplyStage(screenExecutor(executor), fn);
}
//执行完当前任务后,将返回值作为action任务的输入参数进行计算
public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {
return uniAcceptStage(null, action);
}
//执行完当前任务后,将返回值作为action任务的输入参数进行计算
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {
return uniAcceptStage(asyncPool, action);
}
//执行完当前任务后,将返回值作为action任务的输入参数进行计算
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,
Executor executor) {
return uniAcceptStage(screenExecutor(executor), action);
}
//执行完当前任务后,执行action定义的任务
public CompletableFuture<Void> thenRun(Runnable action) {
return uniRunStage(null, action);
}
//执行完当前任务后,执行action任务
public CompletableFuture<Void> thenRunAsync(Runnable action) {
return uniRunStage(asyncPool, action);
}
//执行完当前任务后,执行action任务,action任务使用executor的线程执行
public CompletableFuture<Void> thenRunAsync(Runnable action,
Executor executor) {
return uniRunStage(screenExecutor(executor), action);
}
//执行完当前任务,和另一个CompletableFuture的任务other,将两个任务的返回值作为参数执行fn,返回该计算过程的CompletableFuture
public <U,V> CompletableFuture<V> thenCombine(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn) {
return biApplyStage(null, other, fn);
}
//执行完当前任务,和另一个CompletableFuture的任务other,将两个任务的返回值作为参数执行fn,返回该计算过程的CompletableFuture
public <U,V> CompletableFuture<V> thenCombineAsync(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn) {
return biApplyStage(asyncPool, other, fn);
}
//执行完当前任务,和另一个CompletableFuture的任务other,将两个任务的返回值作为参数执行fn,返回该计算过程的CompletableFuture,计算过程中会使用executor的线程计算
public <U,V> CompletableFuture<V> thenCombineAsync(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn, Executor executor) {
return biApplyStage(screenExecutor(executor), other, fn);
}
//执行完当前任务,和另一个CompletableFuture的任务other,将两个任务的返回值作为参数执行fn
public <U> CompletableFuture<Void> thenAcceptBoth(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action) {
return biAcceptStage(null, other, action);
}
//执行完当前任务,和另一个CompletableFuture的任务other,将两个任务的返回值作为参数执行fn
public <U> CompletableFuture<Void> thenAcceptBothAsync(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action) {
return biAcceptStage(asyncPool, other, action);
}
//执行完当前任务,和另一个CompletableFuture的任务other,将两个任务的返回值作为参数执行fn,计算过程使用executor的线程执行
public <U> CompletableFuture<Void> thenAcceptBothAsync(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action, Executor executor) {
return biAcceptStage(screenExecutor(executor), other, action);
}
//在当前任务和另一个CompletableFuture的任务执行完毕后,执行action
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,
Runnable action) {
return biRunStage(null, other, action);
}
//在当前任务和另一个CompletableFuture的任务执行完毕后,执行action
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action) {
return biRunStage(asyncPool, other, action);
}
//在当前任务和另一个CompletableFuture的任务执行完毕后,执行action,计算过程会使用executor的线程执行
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action,
Executor executor) {
return biRunStage(screenExecutor(executor), other, action);
}
//计算当前任务与other的任务,计算快的返回结果作为fn的输入进行计算,并返回计算结果的CompleteFuture
public <U> CompletableFuture<U> applyToEither(
CompletionStage<? extends T> other, Function<? super T, U> fn) {
return orApplyStage(null, other, fn);
}
//计算当前任务与other的任务,计算快的返回结果作为fn的数据进行计算,并返回计算结果的CompleteFuture
public <U> CompletableFuture<U> applyToEitherAsync(
CompletionStage<? extends T> other, Function<? super T, U> fn) {
return orApplyStage(asyncPool, other, fn);
}
//计算当前任务与other的任务,计算快的返回结果作为fn的输入进行计算,并返回计算结果的CompleteFuture,计算过程会使用executor的线程执行
public <U> CompletableFuture<U> applyToEitherAsync(
CompletionStage<? extends T> other, Function<? super T, U> fn,
Executor executor) {
return orApplyStage(screenExecutor(executor), other, fn);
}
//计算当前任务与other的任务,计算快的返回结果作为action的输入进行计算
public CompletableFuture<Void> acceptEither(
CompletionStage<? extends T> other, Consumer<? super T> action) {
return orAcceptStage(null, other, action);
}
//计算当前任务与other的任务,计算快的返回结果作为action的输入进行计算
public CompletableFuture<Void> acceptEitherAsync(
CompletionStage<? extends T> other, Consumer<? super T> action) {
return orAcceptStage(asyncPool, other, action);
}
//计算当前任务与other的任务,计算快的返回结果作为action的输入进行计算,计算过程使用executor的线程执行
public CompletableFuture<Void> acceptEitherAsync(
CompletionStage<? extends T> other, Consumer<? super T> action,
Executor executor) {
return orAcceptStage(screenExecutor(executor), other, action);
}
//当前任务和other的任务,只要有一个任务完成,就执行action
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,
Runnable action) {
return orRunStage(null, other, action);
}
//当前任务和other的任务,只要有一个任务完成,就执行action
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
Runnable action) {
return orRunStage(asyncPool, other, action);
}
//当前任务和other的任务,只要有一个任务完成,就执行action,所有计算过程使用executor的线程
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
Runnable action,
Executor executor) {
return orRunStage(screenExecutor(executor), other, action);
}
//在当前的任务完成后,生成一个新的CompletableFuture
public <U> CompletableFuture<U> thenCompose(
Function<? super T, ? extends CompletionStage<U>> fn) {
return uniComposeStage(null, fn);
}
//在当前的任务完成后,生成一个新的CompletableFuture,与thenApply需要注意区别
public <U> CompletableFuture<U> thenComposeAsync(
Function<? super T, ? extends CompletionStage<U>> fn) {
return uniComposeStage(asyncPool, fn);
}
//在当前的任务完成后,生成一个新的CompletableFuture,计算过程使用executor的线程
public <U> CompletableFuture<U> thenComposeAsync(
Function<? super T, ? extends CompletionStage<U>> fn,
Executor executor) {
return uniComposeStage(screenExecutor(executor), fn);
}
//在当前任务完成后,执行action。该方法不会使用ForkJoinPool的线程,需要与thenapply区分
public CompletableFuture<T> whenComplete(
BiConsumer<? super T, ? super Throwable> action) {
return uniWhenCompleteStage(null, action);
}
//在当前任务完成后,执行action
public CompletableFuture<T> whenCompleteAsync(
BiConsumer<? super T, ? super Throwable> action) {
return uniWhenCompleteStage(asyncPool, action);
}
//在当前任务完成后,执行action,action是使用executor线程池执行
public CompletableFuture<T> whenCompleteAsync(
BiConsumer<? super T, ? super Throwable> action, Executor executor) {
return uniWhenCompleteStage(screenExecutor(executor), action);
}
CompleteFuture不带Async和带Async方法的区别:
- 带Async的方法比较简单,就是每个计算过程都会使用线程池中的线程来执行,如果没有指定使用的线程池,那么会使用默认的ForkJoinPool,如果指定了Executor,那么直接使用指定的线程池即可。
- 不带Async的方法执行较为复杂,要分成两种情况。
以thenAccept方法为例:
第一种情况,在任务A还没执行完的时候,主线程就通过thenAccept方法设置了任务A执行完后要执行任务B,代码和对应的输出结果如下:
CompletableFuture<String> completableFuture=CompletableFuture.supplyAsync(()->{
//分配了ForkJoinPool的线程执行
System.out.println("task A: "+Thread.currentThread());
try {
Thread.sleep(2000);
}catch (Exception e){
e.printStackTrace();
}
return "task A";
});
System.out.println(Thread.currentThread());
//Thread.sleep(5000);
completableFuture.thenAccept(str->{
System.out.println("task B: "+Thread.currentThread());
});
输出结果:
Thread[main,5,main]
task A: Thread[ForkJoinPool.commonPool-worker-11,5,main]
task B: Thread[ForkJoinPool.commonPool-worker-11,5,main]
第二种情况,设置的任务A已经被子线程执行完毕,但是主线程还没通过thenAccept方法去设置后续任务B的操作,那么这个时候,只能由主线程执行任务B的操作,代码和输出如下:
CompletableFuture<String> completableFuture=CompletableFuture.supplyAsync(()->{
//分配了ForkJoinPool的线程执行
System.out.println("task A: "+Thread.currentThread());
try {
Thread.sleep(2000);
}catch (Exception e){
e.printStackTrace();
}
return "task A";
});
System.out.println(Thread.currentThread());
//等待子线程将任务A计算完成,再去设置任务B
Thread.sleep(5000);
completableFuture.thenAccept(str->{
System.out.println("task B: "+Thread.currentThread());
});
}
输出结果:
Thread[main,5,main]
task A: Thread[ForkJoinPool.commonPool-worker-11,5,main]
task B: Thread[main,5,main]