Java8 CompletableFuture 总结
Posted 小兵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java8 CompletableFuture 总结相关的知识,希望对你有一定的参考价值。
原文链接:https://fxbing.github.io/2019...
CompletableFuture
是Java8 中新增的用来进行函数式异步编程的工具类。
最近学习源码的过程中看到有很多 CompletableFuture
的使用,感觉自己对这个类中的各个方法的使用场景和方法不是很熟悉,遂参考了下面几篇博客进行学习(本文大部分内容也都来自下面几篇博客):
Java CompletableFuture 详解
Java8新的异步编程方式 CompletableFuture(一)
Java8新的异步编程方式 CompletableFuture(二)
Java8新的异步编程方式 CompletableFuture(三)
上面的博客介绍的比较详细,为了自己查阅回看的方便,这里对这些方法进行一下总结(这里只总结不举例,具体使用需要看上面的博客)。
Future接口
Feture
接口包含五个方法,介绍如下:
boolean cancel (boolean mayInterruptIfRunning)
取消任务的执行。参数指定是否立即中断任务执行,或者等等任务结束boolean isCancelled ()
任务是否已经取消,任务正常完成前将其取消,则返回true
boolean isDone ()
任务是否已经完成。需要注意的是如果任务正常终止、异常或取消,都将返回true
V get () throws InterruptedException, ExecutionException
等待任务执行结束,然后获得V类型的结果。InterruptedException 线程被中断异常, ExecutionException任务执行异常,如果任务被取消,还会抛出CancellationExceptionV get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
同上面的get功能一样,多了设置超时时间。参数timeout指定超时时间,uint指定时间的单位,在枚举类TimeUnit中有相关的定义。如果计 算超时,将抛出TimeoutException
主动完成计算
CompletableFuture
实现了CompletionStage
和Future
两个接口。
通过阻塞或者轮询获得结果
方法名 | 描述 |
---|---|
public T get() | Future 接口实现 |
public T get(long timeout, TimeUnit unit) | Future 接口实现 |
public T getNow(T valueIfAbsent) | 如果结果已经计算完则返回结果或者抛出异常,否则返回给定的valueIfAbsent 值。 |
public T join() | 返回计算的结果或者抛出一个unchecked异常(CompletionException) |
join()
和get()
的区别是,join()
只会抛出未检查异常(不需要使用try...catch..
进行处理),而get()
会抛出检查异常。
异步获取结果
- 下面两个函数的调用会立即执行,并且只能执行一次。
- 如果该任务已经执行完成,那么下面两个调用会无效,只能获取执行完成的结果。其实就是使任务立即结束(返回指定结果或者指定抛出异常)。
- 比较适合需要返回
CompletableFuture
的方法,先创建一个空的CompletableFuture
,之后通过下面两个函数指定前面创建的CompletableFuture
的返回值。
方法名 | 描述 |
---|---|
complete(T t) | 完成异步执行,并返回future的结果 |
completeExceptionally(Throwable ex) | 异步执行不正常的结束 |
静态工厂方法
run 和 supply 的主要区别是异步操作是否有返回值(下面列出的所有方法也基本都是按照是否有返回值分为两类)。
方法名 | 描述 |
---|---|
runAsync(Runnable runnable) | 使用ForkJoinPool.commonPool()作为它的线程池执行异步代码。 |
runAsync(Runnable runnable, Executor executor) | 使用指定的thread pool执行异步代码。 |
supplyAsync(Supplier<U> supplier) | 使用ForkJoinPool.commonPool()作为它的线程池执行异步代码,异步操作有返回值。 |
supplyAsync(Supplier<U> supplier, Executor executor) | 使用指定的thread pool执行异步代码,异步操作有返回值。 |
下面几乎所有的方法都是一式三份,三种方法的区别是
- 直接在当前线程执行
- 换另一个线程(但是不指定线程)异步执行
- 指定线程执行
转换
相当于 map 操作
方法名 | 描述 |
---|---|
thenApply(Function<? super T,? extends U> fn) | 接受一个Function<? super T,? extends U>参数用来转换CompletableFuture |
thenApplyAsync(Function<? super T,? extends U> fn) | 接受一个Function<? super T,? extends U>参数用来转换CompletableFuture,使用ForkJoinPool |
thenApplyAsync(Function<? super T,? extends U> fn, Executor executor) | 接受一个Function<? super T,? extends U>参数用来转换CompletableFuture,使用指定的线程池 |
相当于 flatMap 操作
方法名 | 描述 |
---|---|
thenCompose(Function<? super T, ? extends CompletionStage<U>> fn) | 在异步操作完成的时候对异步操作的结果进行一些操作,并且仍然返回CompletableFuture类型。 |
thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) | 在异步操作完成的时候对异步操作的结果进行一些操作,并且仍然返回CompletableFuture类型。使用ForkJoinPool。 |
thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn,Executor executor) | 在异步操作完成的时候对异步操作的结果进行一些操作,并且仍然返回CompletableFuture类型。使用指定的线程池。 |
组合
方法名 | 描述 |
---|---|
thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn) | 当两个CompletableFuture都正常完成后,执行提供的fn,用它来组合另外一个CompletableFuture的结果。 |
thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn) | 当两个CompletableFuture都正常完成后,执行提供的fn,用它来组合另外一个CompletableFuture的结果。使用ForkJoinPool。 |
thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor) | 当两个CompletableFuture都正常完成后,执行提供的fn,用它来组合另外一个CompletableFuture的结果。使用指定的线程池。 |
thenAcceptBoth跟thenCombine类似,但是返回CompletableFuture类型。
方法名 | 描述 |
---|---|
thenAcceptBoth(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> action) | 当两个CompletableFuture都正常完成后,执行提供的action,用它来组合另外一个CompletableFuture的结果。 |
thenAcceptBothAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> action) | 当两个CompletableFuture都正常完成后,执行提供的action,用它来组合另外一个CompletableFuture的结果。使用ForkJoinPool。 |
thenAcceptBothAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> action, Executor executor) | 当两个CompletableFuture都正常完成后,执行提供的action,用它来组合另外一个CompletableFuture的结果。使用指定的线程池。 |
计算结果完成时的处理
Action
的类型是BiConsumer<? super T,? super Throwable>
,它可以处理正常的计算结果,或者异常情况。- 方法不以
Async
结尾,意味着Action
使用相同的线程执行,而Async
可能会使用其它的线程去执行(如果使用相同的线程池,也可能会被同一个线程选中执行
方法名 | 描述 |
---|---|
whenComplete(BiConsumer<? super T,? super Throwable> action) | 当CompletableFuture完成计算结果时对结果进行处理,或者当CompletableFuture产生异常的时候对异常进行处理。 |
whenCompleteAsync(BiConsumer<? super T,? super Throwable> action) | 当CompletableFuture完成计算结果时对结果进行处理,或者当CompletableFuture产生异常的时候对异常进行处理。使用ForkJoinPool。 |
whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor) | 当CompletableFuture完成计算结果时对结果进行处理,或者当CompletableFuture产生异常的时候对异常进行处理。使用指定的线程池。 |
handle()
相当于whenComplete()+转换。
handle()
也可以理解为和thenApply()
的含义更为相似,但是比thenApply()
增加异常处理的功能。
方法名 | 描述 |
---|---|
handle(BiFunction<? super T, Throwable, ? extends U> fn) | 当CompletableFuture完成计算结果或者抛出异常的时候,执行提供的fn |
handleAsync(BiFunction<? super T, Throwable, ? extends U> fn) | 当CompletableFuture完成计算结果或者抛出异常的时候,执行提供的fn,使用ForkJoinPool。 |
handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor) | 当CompletableFuture完成计算结果或者抛出异常的时候,执行提供的fn,使用指定的线程池。 |
方法名 | 描述 |
---|---|
exceptionally(Function fn) | 只有当CompletableFuture抛出异常的时候,才会触发这个exceptionally的计算,调用function计算值。 |
纯消费
方法名 | 描述 |
---|---|
thenAccept(Consumer<? super T> action) | 当CompletableFuture完成计算结果,只对结果执行Action,而不返回新的计算值 |
thenAcceptAsync(Consumer<? super T> action) | 当CompletableFuture完成计算结果,只对结果执行Action,而不返回新的计算值,使用ForkJoinPool。 |
thenAcceptAsync(Consumer<? super T> action, Executor executor) | 当CompletableFuture完成计算结果,只对结果执行Action,而不返回新的计算值 |
Either
Either 表示的是两个CompletableFuture,当其中任意一个CompletableFuture计算完成的时候就会执行。
方法名 | 描述 |
---|---|
acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action) | 当任意一个CompletableFuture完成的时候,action这个消费者就会被执行。 |
acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action) | 当任意一个CompletableFuture完成的时候,action这个消费者就会被执行。使用ForkJoinPool |
acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor) | 当任意一个CompletableFuture完成的时候,action这个消费者就会被执行。使用指定的线程池 |
applyToEither()
是acceptEither()
的哥哥. 当两个future其中一个完成后,后者用于只是简单地调用一些代码,applyToEither()
会返回一个新的future. 这个future是在前面两个future其中一个完成后进行执行完成。
方法名 | 描述 |
---|---|
applyToEither(CompletionStage<? extends T> other, Function<? super T,U> fn) | 当任意一个CompletableFuture完成的时候,fn会被执行,它的返回值会当作新的CompletableFuture<U>的计算结果。 |
applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T,U> fn) | 当任意一个CompletableFuture完成的时候,fn会被执行,它的返回值会当作新的CompletableFuture<U>的计算结果。使用ForkJoinPool |
applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T,U> fn, Executor executor) | 当任意一个CompletableFuture完成的时候,fn会被执行,它的返回值会当作新的CompletableFuture<U>的计算结果。使用指定的线程池 |
其他方法
方法名 | 描述 |
---|---|
allOf(CompletableFuture<?>... cfs) | 在所有Future对象完成后结束,并返回一个future。 |
anyOf(CompletableFuture<?>... cfs) | 在任何一个Future对象结束后结束,并返回一个future。 |
以上是关于Java8 CompletableFuture 总结的主要内容,如果未能解决你的问题,请参考以下文章
Java8新的异步编程方式 CompletableFuture
Java8 增强的Future:CompletableFuture
Java8已经发布7年了,不会还有人没用过CompletableFuture吧