completeFuture作为Doug Lea大师的有一个艺术作品,把并发编程的艺术发挥到极致。之前的Future为我们提供了多线程执行返回值的使用问题。而CompletableFuture则为我们提供了一种线程执行结果连续处理的能力。为多线程编程提供了更为简洁的方式。关于CompletableFuture,我会分为多篇来讲,今天会为大家介绍一下其基本方法以及不同名称参数的方法含义及作用。
1 Completable Future是什么
CompletableFuture 实现了Future,那么也就会有Future的全部功能(其实就是5个方法)。
CompletionStage 是JDK1.8 Doug Lea 设计的一个接口,旨在提高多任务协同执行的编码效率。是一个可异步完成的Stage,可以根据当前Stage的完成情况连续调用,且支持异步计算的各种方法。并有发生异常时的处理方法。
一个Stage的action的执行,可以是在单个stage完成之后,两个stage都完成之后,或者两个stage中有一个正常完成之后。
CompletableFuture实现了CompletionStage接口,那么其stage的这种设计方式也得到了实现。
2 Completable Future 构造及简单使用
2.1 创建CompleteableFuture的方法
- 可以直接new一个CompleteableFuture。
- 可以调用supplyAsync静态方法去异步执行,返回一个带有result的CompleteableFuture。
- 静态方法runAsync异步执行后返回一个没有result的CompleteableFuture
- 也可以使用静态方法completedFuture,直接返回一个完成状态的CompleteableFuture。
示例
CompleteableFuture 其主要方法大多为CompletionStage相关的方法。
- thenCompose 平行处理两个
- thenCombine 聚合两个stage的result
- thenAccept 直接消费
- thenRun 直接执行
- theApply
我们先列出来,后面会一一讲到。
2.2 从CompleteableFuture中获取执行结果
相关方法有
- join() 没有抛出检查的异常,会阻塞等待执行结果。
- get() 会抛出检查异常,会阻塞等待执行结果
- getNow(T valueIfAbsent) 不会阻塞
3 Completable Future 各方法介绍
CompleteableFuture实现了CompletionStage,其相关方法比较多。我们分组来介绍。
3.1 主要参数为Supplier的方法
Supplier的Lamada表达式没有输入值,但是有返回值。
supplyAsync 会异步执行Supplier方法,然后返回一个带有Result的CompletableFuture。
completeAsync(Supplier<? extends T> supplier)
使用默认的线程池来异步执行Supplier方法,将其结果作为此CompletableFuture的result,来完成此CompletableFuture. 另一个方法为使用自定义线程池。
3.2 主要参数为Runnable的方法
Runnable标记了函数式接口,其唯一的方法无参数,且无返回值。所以相关方法中返回的的CompletableFuture也不包含返回值。相关Runable的方法如下。
3.2.1 静态方法。
runAsync(Runnable runnable) 是一个静态方法,在给定的任务完成后,将使用ForkJoinPool.commonPool() 线程池来异步执行相关任务,并返回CompletableFuture,但是CompletableFuture中没有执行的结果。Runable为参数的方法中返回的CompletableFuture对象都不包含其执行结果。
**runAsync(Runnable runnable,Executor executor)**也是静态方法,不同的是使用了自定义的线程池。
3.2.2 thenRun系列
thenRun(Runnable action) 是CompletableFuture对象的一个方法,表示在调用方即CompletionStage(CompletableFuture实现了CompletionStage,所以也就可以表示任务完成的状态)正常完成的情况下会执行这个动作。
thenRunAsync(Runnable action) 表示在当前调用方正常完成任务时异步执行此动作,默认使用ForkJoinPool.commonPool()线程池来执行任务。
同理 thenRunAsync(Runnable action,Executor executor) 可以使用自定义线程池来异步执行
小结:
- 方法中带有Async,则表示当前调用方正常完成任务时异步执行当前动作,默认使用ForkJoinPool.commonPool()线程池执行。
- 方法中带有Async,参数中有Executor,则表明可以使用自定义线程池。
后面的讲解就只说明不带Async的方法了。
3.2.3 runAfterBoth
runAfterBoth(CompletionStage<?> other,Runnable action)
表示当前调用方以及参数中给定的Stage都正常完成任务时才执行当前动作
3.2.4 runAfterEither
runAfterEither(CompletionStage<?> other,Runnable action)
这个不用我说你都能才出来了吧。表示当前调用方以及参数中给定的Stage任何一个Stage正常完成任务就执行当前动作。
3.3 主要参数为Function的方法
Functioin接口定义T为输入值R为输出值。便是此Lamada表达式包含了输入输出值。
3.3.1 thenApply
thenApply(Function<? super T,? extends U> fn)
当前Stage正常完成后,再执行此Function任务,并且会将当前的Stage结果作为Function中的参数。最后返回一个CompletionStage。
其余方法同上面讲的一样,均是默认线程池异步执行,或使用自定义线程池异步执行。