目录
1、创建CompletableFuture的方式
1.1 使用new方式创建
public CompletableFuture()
public static <U> CompletableFuture<U> completedFuture(U value)
1.2 使用静态方法创建
有返回值的任务用run*,无返回值的任务用supply*。建议自定义线程池。
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
2、获得执行结果
//阻塞式获取执行结果
T get() throws InterruptedException, ExecutionException
//如果阻塞等待过程中超时则会抛出TimeoutException异常。
T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
//如果任务完成则直接返回执行完成后的结果,如果任务没有完成,则返回调用方法时传入的参数valueIfAbsent值,不会修改get()返回的值
T getNow(T valueIfAbsent)
//如果操作未执行完就将get获得的值改为给定的值,然后返回true,反之get获得的值就是操作执行完返回的值,然后返回false
boolean complete(T value)
//和get()方法作用一样,只是不会抛出异常
T join()
3、结果&异常处理
whenComplete 与 handle 方法就类似于 try..catch..finanlly 中 finally 代码块。无论是否发生异常,都将会执行的。
如果不希望某个节点抛出异常导致后续流程中断,则可在节点的处理中捕获并包装为结果、或者对子 CompletableFuture 节点采用 handle、exceptionally API转换异常。
whenComplete*方法:之前任务执行完成后继续执行whenComplete里的内容(whenComplete传入的action只是对之前任务的结果进行处理),即使用该方法可以避免前面说到的Future接口的问题,不再需要通过阻塞或者轮询的方式去获取结果,而是通过调用该方法等任务执行完毕自动调用。
该方法的参数为BiConsumer<? super T, ? super Throwable> 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)
handle*方法:消费前面的结果及异常信息,具有返回值,不会中断后续任务,可以通过handle为之前出现异常无法获得的结果重新赋值。
handle(BiFunction<? super T, Throwable, ? extends U> fn)的参数是消费者接口,一个参数是任务执行结果,一个是异常信息,并且具有返回值。
public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn)
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn)
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor)
exceptionally 使用方式类似于 try..catch 中 catch代码块中异常处理。
public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn)
4、串行执行另外的任务
thenRun** 前面任务执行完后执行当前任务,不关心前面任务的结果,没有传入参数,也没返回值。
public CompletableFuture<Void> thenRun(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action, Executor executor)
thenAccept** 前面任务执行完后执行当前任务,消费前面的结果,没有返回值。
thenAccept(Consumer<? super T> action)的参数为消费者接口,即可以传入一个参数,该参数为上一个任务的执行结果。
public CompletableFuture<Void> thenAccept(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor)
thenApply** 前面任务执行完后执行当前任务,消费前面的结果,具有返回值。
thenApply(Function<? super T,? extends U> fn)的参数为函数式接口,即可以传入一个参数类型为T,该参数是上一个任务的执行结果,并且函数式接口需要有返回值,类型为U。
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)
5、两组任务按顺序执行
thenCompose** 实现两组任务按前后顺序执行。
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, ? extendsCompletionStage<U>> fn,Executor executor)
thenApply与thenCompose的区别:
可以看到,两个方法的返回值都是CompletionStage<U>,不同之处在于它们的传入参数fn.
对于thenApply,fn函数是一个对一个已完成的stage或者说CompletableFuture的的返回值进行计算、操作;
对于thenCompose,fn函数是对另一个CompletableFuture进行计算、操作。
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> 100).thenApply(num -> num + " to String");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> 100).thenCompose(num -> CompletableFuture.supplyAsync(() -> num + " to String"));
System.out.println(f1.join()); // 100 to String
System.out.println(f2.join()); // 100 to String
例子中,thApply和thenCompose都是将一个CompletableFuture<Integer>转换为CompletableFuture<String>。
不同的是,thenApply中的传入函数的返回值是String,而thenCompose的传入函数的返回值是CompletableFuture<String>。
6、两组任务完成后合并
thenCombine** 等待两组任务执行完毕后,合并两组任务的执行结果。有入参,有返回值。
该方法用于两组任务都完成后,将两组任务的执行结果一起交给当前方法的BiFunction处理。先完成的任务会等待后者任务完成。
public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn, Executor executor)
thenAcceptBoth**,只有入参,无返回值。
public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor)
runAfterBoth**,无入参,无返回值。
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor)
7、两组任务谁先执行完就用谁的结果
applyToEither** 比较两组任务执行速度,谁快消费谁的执行结果。有入参,有返回值。
public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor)
acceptEither**,只有入参,无返回值。
public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor)
runAfterEither**,无入参,无返回值。
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor)
8、多任务组合
allOf** 实现并行地执行多个任务,等待所有任务执行完成(无需考虑执行顺序)。
该方法可以实现并行地执行多个任务,适用于多个任务没有依赖关系,可以互相独立执行的,传入参数为多个任务,没有返回值。
allOf()方法会等待所有的任务执行完毕再返回,可以通过get() 或join() 阻塞确保所有任务执行完毕。
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
anyOf** 实现并行地执行多个任务,只要有个一个完成的便会返回执行结果。
该方法可以实现并行地执行多个任务,传入参数为多个任务,具有返回值。该方法不会等待所有任务执行完成后再返回结果,而是当有一个任务完成时,便会返回那个任务的执行结果。
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
public CompletableFuture()
public static <U> CompletableFuture<U> completedFuture(U value)