本篇继续介绍CompletableFuture的高阶使用方式。
CompletableFuture的supplyAsync配合allOf,将所有的future绑定到一起,然后所有都执行完之后触发对应操作,demo:
allOf方法内部调用了andTree方法,看方法注释,该方法会根据传入的参数递归生成一棵树
这段代码可能看起来有点绕,我们举个具体的例子,比如添加5个任务,那么cfs是个size为5的数组,lo是0,hi是4,根据这组参数,树的构成逻辑如下:
根据0和4得到mid为2,对a来说,不满足条件继续递归,所以到下面0和2得到mid为1。对b来说,也不满足条件,继续递归,所以到下面3和4得到mid为3。后续以此来推。经过递归最终生成的树如下图所示:
先解释下这棵树的画法,方形中的三个数字代表andTree方法中的lo,mid和hi,数字i的圆形代表cfs的第i个元素,即cfs[i]。那么根据这棵树,我们将任务两两组合了,一共生成了4个任务:
1)任务0和1组成一对,它们组合在一起起个名字叫做0-1,这里a=cfs[0],b=cfs[1],同时创建了一个叫做d的CompletableFuture,这里叫它d01,作为返回值
2)任务0-1又和任务2组成一对,起个名字叫做0-1-2,这里a=d01,b=cfs[2],同时创建一个CompletableFuture,这里叫它d012,作为返回值
3)任务3和任务4组成一对,叫做3-4,这里a=cfs[3],b=cfs[4],同时创建一个CompletableFuture,这里叫它d34,作为返回值
4)任务0-1-2和任务3-4组成一对,叫做0-1-2-3-4,这里a=d012,b=d34,同时创建一个CompletableFuture,这里叫它d01234
所以:
对1)来说,a=cfs[0],b=cfs[1]都完成之后,会触发d01。
对2)来说,d01和cfs[2]都执行完会触发d012。
对3)来说,a=cfs[3],b=cfs[4]都执行完会触发d34。
对4)来说,d012和d34都执行完之后会触发d01234。
除此之外,allOf得到的最后一个future的触发,是由最晚执行完的那个任务去触发的,从上面的demo中可以看出,打印hello这个任务的线程和最终future任务的线程是同一个线程。