简单解析
首先尝试不看源码情况下讲清楚CompletableFuture. CompletableFuture主要由两个类组成,CompletableFuture与Completion,其中Completion有非常多实现类,像是一元的UniCompletion,二元的BiCompletion等,整体逻辑都是差不多的,这里以基于一元UniCompletion的UniApply来讲解.
cf1是被观察者,当cf1 result为null时候,这时候执行thenApply,会生成一个UniApply对象加入到cf1 stack中,当cf1 result有值以后,会执行stack中每一个Completion.
源码解析
uniApplyStage
//执行thenApply后调用此函数
private <V> CompletableFuture<V> uniApplyStage(
Executor e, Function<? super T,? extends V> f) {
if (f == null) throw new NullPointerException();
Object r;
//当前cf result不为空的话,不需要入栈,直接执行
if ((r = result) != null)
return uniApplyNow(r, e, f);
CompletableFuture<V> d = newIncompleteFuture();
//构建一个UniApply,入栈到当前cf的stack
unipush(new UniApply<T,V>(e, d, this, f));
return d;
}
postComplete
public boolean complete(T value) {
//cas方式赋值result
boolean triggered = completeValue(value);
postComplete();
return triggered;
}
final void postComplete() {
CompletableFuture<?> f = this; Completion h;
while ((h = f.stack) != null ||
(f != this && (h = (f = this).stack) != null)) {
CompletableFuture<?> d; Completion t;
//f的stack由h替换成h.next
if (STACK.compareAndSet(f, h, t = h.next)) {
if (t != null) {
//如果h后面还有completion即t,且f不是当前cf,把h入栈到当前cf
if (f != this) {
pushStack(h);
continue;
}
NEXT.compareAndSet(h, t, null); // try to detach
}
//h.tryFire如果h.dep的stack不会空的话会返回d,f此时就是h.dep不再是当然cf
f = (d = h.tryFire(NESTED)) == null ? this : d;
}
}
}
postComplete这段有点难以理解,我当时看的时候也没用一下子看懂,还是文字+示例说明下
CompletableFuture<String> cf1 = new CompletableFuture<>();
CompletableFuture<String> cf1_1 = cf1.thenApply(x -> {
log.info("1_1");
return x + "_1";
});
CompletableFuture<String> cf1_2 = cf1.thenApply(x -> {
log.info("1_2");
return x + "_2";
});
CompletableFuture<String> cf1_2_1 = cf1_2.thenApply(x -> {
log.info("1_2_1");
return x + "_1";
});
CompletableFuture<String> cf1_2_2 = cf1_2.thenApply(x -> {
log.info("1_2_2");
return x + "_2";
});
cf1.complete("1");
/**
打印结果如下
1_2
1_2_1
1_2_2
1_1
**/
- 首先cf1_1的completion入cf1的栈,成为栈顶 (以下都会把completion省略掉,直接写cf1_1)
- cf1_2入cf1的栈,成为栈顶,cf1栈内数据目前如下cf1_2->cf1_1
- cf1_2_1入cf1_2的栈
- cf1_2_2入cf1_2的栈,cf1_2栈内数据如下cf1_2_2->cf1_2_1
- 接下来执行cf1.complete,complete函数内执行postComplete
- 首先cf1_2出栈并执行,打印1_2
- h.tryFire因为cf1_2栈内非空,返回的是cf1_2的cf,此时f为cf1_2
- cf1_2出栈第一条为cf1_2_2,由于cf1_2_2后面还有cf1_2_1,所以把cf1_2_2入栈到cf1,此时cf1栈内数据cf1_2_2->cf1_1
- cf1_2出栈下一条为cf1_2_1,由于此时cf1_2栈内没有下一条了,直接执行cf1_2_1,不需要再入栈了,打印1_2_1
- cf1_2_1栈内为空,所以此时f为cf1_1
- 继续cf1_1出栈,栈顶为cf1_2_2,打印1_2_2
- 继续cf1_1出栈,栈顶为cf1_1,打印1_1
通过示例可以说明,postComplete函数做的事情就是执行当前cf的栈,对于栈内每个completion,如果completion的dep的stack不为空,就把dep stack都加入到当前cf的stack内,对于dep stack最后一个completion,直接执行,不加入到cf的stack内.
tryFire
final CompletableFuture<V> tryFire(int mode) {
CompletableFuture<V> d; CompletableFuture<T> a;
Object r; Throwable x; Function<? super T,? extends V> f;
if ((a = src) == null || (r = a.result) == null
|| (d = dep) == null || (f = fn) == null)
return null;
//执行fn的前提是d.result=null
tryComplete: if (d.result == null) {
//实现了AltResult,代表返回结果可能是null,或者抛出异常了
if (r instanceof AltResult) {
if ((x = ((AltResult)r).ex) != null) {
d.completeThrowable(x, r);
break tryComplete;
}
r = null;
}
try {
//mode<=0表示当前completion是在出栈时候被调用或者在加入栈时候发现已经有result
//claim将status设置为1,表示当前completion被执行
//claim如果当前线程执行返回true,线程池执行返回false
if (mode <= 0 && !claim())
return null;
else {
@SuppressWarnings("unchecked") T t = (T) r;
d.completeValue(f.apply(t));
}
} catch (Throwable ex) {
d.completeThrowable(ex);
}
}
src = null; dep = null; fn = null;
return d.postFire(a, mode);
}
final boolean claim() {
Executor e = executor;
if (compareAndSetForkJoinTaskTag((short)0, (short)1)) {
if (e == null)
return true;
executor = null; // disable
e.execute(this);
}
return false;
}
postFire
final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
//当前cf的前置cf如果stack还不为空,且当前线程和前置cf不是同一个线程时候,帮助前置cf去执行stack
if (a != null && a.stack != null) {
Object r;
if ((r = a.result) == null)
a.cleanStack();
if (mode >= 0 && (r != null || a.result != null))
a.postComplete();
}
if (result != null && stack != null) {
//mode<0代表是由前置cf出栈调用的,将当前cf返回,由前置cf在postComplete函数中将当前cf的栈
//加入到前置cf的栈
if (mode < 0)
return this;
else
//mode>=0表示要么是在线程池中执行,要么执行时前置cf已经有result
postComplete();
}
return null;
}
mode说明
static final int SYNC = 0;
static final int ASYNC = 1;
static final int NESTED = -1;
源码中有很多逻辑都会根据mode来判断,看懂mode还是很有必要的
async
abstract static class Completion extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {
public final void run() { tryFire(ASYNC); }
public final boolean exec() { tryFire(ASYNC); return false; }
}
mode=async只会在completion继承Runnable的run方法中使用,即ASYNC代表当前执行tryFire是在线程中执行
sync
final void unipush(Completion c) {
if (c != null) {
while (!tryPushStack(c)) {
if (result != null) {
NEXT.set(c, null);
break;
}
}
if (result != null)
c.tryFire(SYNC);
}
}
mode=sync只会在执行cf1.thenApply这种操作时候当入栈时候发现result不为空时候执行,sync表示执行tryFire的线程为执行cf1.thenApply的线程
nested
final void postComplete() {
/*
* On each step, variable f holds current dependents to pop
* and run. It is extended along only one path at a time,
* pushing others to avoid unbounded recursion.
*/
CompletableFuture<?> f = this; Completion h;
while ((h = f.stack) != null ||
(f != this && (h = (f = this).stack) != null)) {
CompletableFuture<?> d; Completion t;
if (STACK.compareAndSet(f, h, t = h.next)) {
if (t != null) {
if (f != this) {
pushStack(h);
continue;
}
NEXT.compareAndSet(h, t, null); // try to detach
}
f = (d = h.tryFire(NESTED)) == null ? this : d;
}
}
}
mode=nested表示执行completion.tryFire是由其他cf出栈并且执行的,执行线程为出栈的那个线程