CompletableFuture的使用方式有很多,但是殊途同归,很多用法在底层原理上是相同的,我们这里找几种典型的使用场景,从易到难,逐步揭开CompletableFuture源码的神秘面纱。
1.举例
首先上个最简单的例子:
1)thenRun配合complete
CompletableFuture配合thenRun和complete方法,通过complete触发thenRun。demo样例:
源码分析:
先看thenRun流程
①调用thenRun的时候,会调用uniRunStage。
这里首先会创建一个CompletableFuture,叫做dep。调用dep的uniRun方法,此时this的result是null,所以该方法返回false。继续向下执行。
然后构造UniRun对象,包含了上述dep。相应的,用户构造的CompletableFuture叫做src。
②然后调用push将UniRun对象压栈。
根据注释,如果result有内容说明已经设置过结果了,就不会再操作,否则就调用tryPushStack方法压栈。如果压栈失败则将next清掉。tryPushStack失败且result是空的情况下,该循环会一直进行下去,直到result被设置(少部分场景)或者tryPushStack(大部分场景)竞争压栈成功。
这里会将Completion的next字段设置为next,该操作不是原子的,因为每次执行到这里,c都是重新构造出来的,所以不存在多线程竞争问题。
这里会设置next字段,同时原子设置stack字段。这里使用原子操作是因为当前CompletableFuture(src)可能会多个线程同时操作,有并发问题。最终竞争成