前面学习了线程池相关的知识,它主要提供异步执行任务,而今天学习的不仅能够异步执行任务,还能把需要分阶段的任务进行分阶段执行。
CompletableFuture介绍
CompletableFuture类实现了CompletionStage与Future接口。CompletionStage翻译过来就是完成阶段,表示任务的每个阶段,然后它声明了一些接下来对任务处理方式,而CompletableFuture是它的实现者。
可以把CompletableFuture看成流水线上的单元,一个单元完成可以触发下一个单元的执行,完成后接着触发下一个,直到所有单元完成,最终会产生一个最终结果。
CompletableFuture也实现了Future接口, 代表一个异步执行的任务,可以获取异步完成后结果。所以CompletableFuture也可以当做一个Future,n那么就能够显式地完成这个Future。
所以CompletableFuture表示一个阶段,也可以被当做一个任务,相当于把流水线分成了各个任务,所以是阶段与任务的综合体。
主要方法介绍
CompletableFuture提供的方法很多,并且大多数CompletableFuture方法都会返回一个CompletableFuture,然后再继续调用新的方法,所以后面把调用方法的阶段对象叫做前一个阶段,而这个方法则表示这个阶段。
这里先把方法进行分类,分类总结图如下图:
首先是以Async结尾的方法,它表示要执行的阶段将会异步的执行,这类方法都可以传递一个executor(线程池)进去,指定线程池去异步执行,如果没有指定则会使用默认的通过ForkJoinPool实现。
后续其他方法基本上都可以和Async(除了anyof与allof),如果方法有Async则表示是异步执行,否则是同步执行。
然后我们来看以thenApply开头的方法,thenApply可以分成两个部分:
then表示这个阶段的动作发生当前的阶段正常完成之后。
Apply表示这个阶段会使用前一个阶段(调用这个方法的阶段对象)返回的结果作为参数。
thenApply如果后面接了Async则表示下一个阶段会采用异步执行,如果没有则会使用同一个线程继续执行,后面的方法也差不多。
然后就是一个thenAccept开头的方法了,它实际上和thenApply差不多,只不过它接受的参数是Consumer,也就是是一个存消费者,并不返回值。如果下一阶段接收了当前阶段的结果,但是在计算的时候不需要返回值(它的返回类型是void)。
applyToEither可以处理两个阶段,当前阶段与作为参数传递进去的other阶段,只要其中一个完成那么另外一个参数fn就会执行。也就是它的功能是只要任何一个阶段完成就可以进入下一个阶段了。acceptEither与applyToEither的区别就和thenAccept和thenApply区别一样。
runAfterBoth方法就像上面那类方法相反,必须要两个阶段的任务完成后才能进入下一个阶段;thenAcceptBoth方法接受的参数是CompletableFuture与BiConsumer,BiConsumer可以接受他们两个的结果然后进行计算;
同样thenCombine方法也能获取到前面两个阶段的结果,这两个阶段相互独立,然后把两个结果进行整合;
thenCompose表面上看起来也是一个阶段的结果放到另外的阶段上,但是它有不一定的不同,它是新建一个阶段,这个阶段会有多个后续阶段,而最开始的结果可以作为新的阶段的任意一个阶段使用。就好像一个工作的单元的产品可以作为另外一个流水线的任意单元使用。
anyOf方法接受一个CompletableFuture集合,只要集合中任意一个完成中使用whenComplete(BiConsumer
allOf方法与anyOf方法差不多,只不过它是等所有的CompletableFuture完成后才处理whenComplete。
案例
方法都介绍完了,在做一个案例具体化,案例如下图:
这个案例比较简单,并且把每一步都返回用变量来接受了。
总结
每个CompletableFuture就像流水线中的一个步骤,它可以等待其他一个或多个完成,或者其中一个完成,也可以在它完成后让其他阶段执行。
CompletableFuture还是比较复杂的,尤其功能很多,这里只做了大方向的归类,具体使用还是要在具体场景中去验证。
Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!
领取专属 10元无门槛券
私享最新 技术干货