CompletableFuture实际操作的源码追究
在此之前整体框架:
Completion:封装了执行任务,以及该任务所依赖的其他任务的结果,在执行任务时进行不同的操作。CompletableFuture:对任务结果的一些操作的封装,以及构建和处理Completion任务依赖的关系。
任务初始化:supplyAsync
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
return asyncSupplyStage(ASYNC_POOL, supplier);
}
asyncSupplyStage方法
asyncSupplyStage方法会返回一个CompletableFuture供我们使用。
static <U> CompletableFuture<U> asyncSupplyStage(Executor e,
Supplier<U> f) {
if (f == null) throw new NullPointerException();
CompletableFuture<U> d = new CompletableFuture<U>();
e.execute(new AsyncSupply<U>(d, f));
return d;
}
其实就是创建了一个AsyncSupply交由线程池进行异步处理。这里的AsyncSupply是一个ForkJoinTask,也是一个Completion。
AsyncSupply类
static final class AsyncSupply<T> extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {
CompletableFuture<T> dep; Supplier<? extends T> fn; // dep是本次任务的结果和有关依赖,fn是任务的执行逻辑
AsyncSupply(CompletableFuture<T> dep, Supplier<? extends T> fn) {
this.dep = dep; this.fn = fn;
}
public final Void getRawResult() { return null; }
public final void setRawResult(Void v) {}
public final boolean exec() { run(); return false; }
public void run() {
CompletableFuture<T> d; Supplier<? extends T> f;
if ((d = dep) != null && (f = fn) != null) {
dep = null; fn = null;
if (d.result == null) {
try {
d.completeValue(f.get()); // <1>
} catch (Throwable ex) {
d.completeThrowable(ex);
}
}
d.postComplete();
}
}
}
<1>执行任务fn.get,并将得到的结果封装到dep.result,result会作为一个任务是否被执行过或是否完成的状态的判断。
后续处理操作:thenAccept
// CompletableFuture#thenAccept
public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {
return uniAcceptStage(null, action);
}
uniAcceptStage方法
uniAcceptStage方法参数e如果是null就不会进行异步处理。
// CompletableFuture#uniAcceptStage
private CompletableFuture<Void> uniAcceptStage(Executor e,
Consumer<? super T> f) {
if (f == null) throw new NullPointerException();
Object r;
if ((r = result) != null)
return uniAcceptNow(r, e, f);
CompletableFuture<Void> d = newIncompleteFuture();
unipush(new UniAccept<T>(e, d, this, f));
return d;
}
// java.util.concurrent.CompletableFuture#unipush
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); // <2> 在UniAccept入栈的过程中,如果已经完成则以SYNC尝试执行。
}
}
thenAccept方法所依赖的CompletableFuture被完成执行uniAcceptNow方法,否则创建UniAccept,并将UniAccept这个任务添加到thenAccept方法所依赖的CompletableFuture的Competion栈中。
然后将新创建的CompletableFuture(对thenAccept方法的Consumer处理)返回。
uniAcceptNow方法
thenAccept方法所依赖的task已经执行完毕,在调用thenAccept方法的时候会进入到该方法。
// CompletableFuture#uniAcceptNow
private CompletableFuture<Void> uniAcceptNow(
Object r, Executor e, Consumer<? super T> f) { // r是当前CompletableFuture.result,e是传递进来的线程池,f是任务执行逻辑
Throwable x;
// Consumer的dep
CompletableFuture<Void> d = newIncompleteFuture();
if (r instanceof AltResult) {
if ((x = ((AltResult)r).ex) != null) {
d.result = encodeThrowable(x, r);
return d;
}
r = null;
}
try {
if (e != null) {
e.execute(new UniAccept<T>(null, d, this, f)); // <1>
} else {
@SuppressWarnings("unchecked") T t = (T) r;
f.accept(t); // <2>
d.result = NIL;
}
} catch (Throwable ex) {
d.result = encodeThrowable(ex);
}
return d;
}
// CompletableFuture#newIncompleteFuture
public <U> CompletableFuture<U> newIncompleteFuture() {
return new CompletableFuture<U>();
}
如果存在线程池则交由线程池执行Consumer,否则由当前线程执行Consumer。
在thenAccept返回的CompletableFuture中已经存在Consumer处理的结果。
UniAccept类
static final class UniAccept<T> extends UniCompletion<T,Void> {
Consumer<? super T> fn;
// <1> 构造方法
// executor:用来异步执行 fn 的线程池,
// dep :对 fn 进行描述的 CompletableFutrue
// src:fn 所依赖的 task 任务 ( src 的完成应该在fn之前)
UniAccept(Executor executor, CompletableFuture<Void> dep,
CompletableFuture<T> src, Consumer<? super T> fn) {
super(executor, dep, src); this.fn = fn;
}
final CompletableFuture<Void> tryFire(int mode) {
CompletableFuture<Void> d; CompletableFuture<T> a;
Object r; Throwable x; Consumer<? super T> f;
if ((d = dep) == null || (f = fn) == null
|| (a = src) == null || (r = a.result) == null)
return null;
tryComplete: if (d.result == null) {
if (r instanceof AltResult) {
if ((x = ((AltResult)r).ex) != null) {
d.completeThrowable(x, r);
break tryComplete;
}
r = null;
}
try {
if (mode <= 0 && !claim())
return null;
else {
@SuppressWarnings("unchecked") T t = (T) r;
f.accept(t);
d.completeNull();
}
} catch (Throwable ex) {
d.completeThrowable(ex);
}
}
dep = null; src = null; fn = null;
return d.postFire(a, mode);
}
}
Completion类
所有的处理逻辑fn,fn对应的结果CompletableFutrue,以及依赖fn的处理结果的其他任务(Completion)等信息,都会被封装成Completion的实现。
之前在supplyAsync方法中将Supplier封装成对应的Completion,然后交由线程池e.execute。那么就会触发Completion.run方法的执行。其实就是调用tryFire(ASYNC)方法。而tryFire方法的实现交由实现类完成。
abstract static class Completion extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {
volatile Completion next; // Treiber stack link
/**
* Performs completion action if triggered, returning a
* dependent that may need propagation, if one exists.
*
* @param mode SYNC, ASYNC, or NESTED
*/
abstract CompletableFuture<?> tryFire(int mode);
/** Returns true if possibly still triggerable. Used by cleanStack. */
abstract boolean isLive();
public final void run() { tryFire(ASYNC); }
public final boolean exec() { tryFire(ASYNC); return false; }
public final Void getRawResult() { return null; }
public final void setRawResult(Void v) {}
}
UniCompletion类
具有源CompletableFutrue、依赖CompletableFutrue以及线程池的Completion。
abstract static class UniCompletion<T,V> extends Completion {
Executor executor; // executor to use (null if none)
CompletableFuture<V> dep; // the dependent to complete
CompletableFuture<T> src; // source for action
UniCompletion(Executor executor, CompletableFuture<V> dep,
CompletableFuture<T> src) {
this.executor = executor; this.dep = dep; this.src = src;
}
/**
* Returns true if action can be run. Call only when known to
* be triggerable. Uses FJ tag bit to ensure that only one
* thread claims ownership. If async, starts as task -- a
* later call to tryFire will run action.
*/
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;
}
final boolean isLive() { return dep != null; }
}
claim方法
claim方法返回true,表示调用claim方法的线程可以执行fn逻辑处理。claim方法返回false,表示fn处理逻辑交由线程池异步处理,原调用线程不用处理了。
claim方法只有在tryFire的mode<=0的时候才可以被调用。
tryFire在什么时候mode>0?那就是线程池通过run进而调用tryFire的时候(可以理解为tryFire被分配到线程池第一次被调用,已经在新线程中了,为什么还要多出来一个线程做无用功)。而mode<=0的时候原线程在调用Completion.postComplete方法做处理,异步处理已经可以执行的fn会提高效率。
isLive方法
表示当前Completion未经过get等方法获取结果。
postComplete方法
postComplete方法会在任务(Completion也是任务)完成对CompletableFuture.result设置之后由该task的CompletableFuture dep调用。而在dep中有一个Completion栈,是对当前处理结果有依赖关系的。postComplete方法就是在调用这些Completion的tryFire方法,进而让他们执行各自逻辑。(其他的Completion在完成处理之后也会在tryFire方法中调用,但是会根据传入的标识而终止递归)
// 将可执行的Completion从stack中弹出,并尝试触发。
// 只有在当前CompletableFuture被完成之后才可以进行操作
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.
*/
//在每一次循环中,f都是当前Completion stack的栈顶弹出的元素,
// f会使用tryFire进行运行。它一次仅沿一条路径扩展,避免无限递归。
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); // <2> 如果有一个tryFire返回不是null,会将其Completion栈中的元素放到当前栈首,然后在开始弹栈执行。
continue;
}
NEXT.compareAndSet(h, t, null); // try to detach
}
f = (d = h.tryFire(NESTED)) == null ? this : d; // <1>
}
}
}
postComplete会尝试执行当前stack的Completion任务。接着在tryFire方法中进行相关执行和处理操作。
<2>可能是应为此时传入的mode=-1,但是没有异步执行,在调用其postFire的时候直接返回this的情况。
tryFire方法
tryFire方法根据策略模式,其实就是根据当前Completion依赖的其他任务的结果(CompletableFutrue)进行相应的逻辑处理。
UniAccept#tryFire
Completion.dep.result是否为null是判断Completion是否被执行过的唯一标识,只能被执行过一次。
// CompletableFuture.UniAccept#tryFire
final CompletableFuture<Void> tryFire(int mode) {
CompletableFuture<Void> d; CompletableFuture<T> a;
Object r; Throwable x; Consumer<? super T> f;
// <1> 因为当前Completion依赖 src.result,所以无法继续处理会直接返回null
if ((d = dep) == null || (f = fn) == null
|| (a = src) == null || (r = a.result) == null)
return null;
tryComplete: if (d.result == null) {
if (r instanceof AltResult) {
if ((x = ((AltResult)r).ex) != null) {
d.completeThrowable(x, r);
break tryComplete;
}
r = null;
}
try {
if (mode <= 0 && !claim()) // <2>
return null;
else {
@SuppressWarnings("unchecked") T t = (T) r;
f.accept(t);
d.completeNull();
}
} catch (Throwable ex) {
d.completeThrowable(ex);
}
}
dep = null; src = null; fn = null;
return d.postFire(a, mode);
}
如果在处理逻辑fn被执行之前,所依赖的CompletableFutrue.result已经被赋值,对于thenAccept方法来说,那么就会在执行该方法的线程执行fn。这中情况不可能被调用tryFire,因为根本就没有产生异步任务Completion。
在非上边的前提下,tryFire有两种被调用的可能:
-
1):在
Completion被线程池执行run方法的时候会以mode=1的状态被调用。CompletableFutrue.result==null:直接返回null,等待被情况2调用。 -
2):在所依赖的
CompletableFutre.result被Completion a在线程池某个线程A完成赋值。会由A线程调用a.postComplete的时候以mode=-1的形式触发。不存在
CompletableFutrue.result==null的情况,所以会经过判断执行CompletableFuture.UniCompletion#claim方法。如果claimf方法返回true,就需要当前线程自行执行fn处理。
postFire
postFire是在CompletableFutrue.result完成赋值之后执行的。也就是说之后当前Completion c执行结束之后,才会通过postComplete方法先去执行c所依赖的CompletableFutrue的Completion栈,再去执行c在CompletableFutrue中保存的依赖c的结果的Completion栈。这个是建立在mode>=0的前提的,否则会将this返回。(即tryFire是以异步的形式调用的,或者是同步的形式调用的,而不是在依赖结果执行完毕之后被动调用。不然会直接返回this,追溯到tryFire被调用)
// CompletableFuture#postFire(java.util.concurrent.CompletableFuture<?>, int)
final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
// a 是 this 所依赖的 结果 CompletableFutrue
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) {
if (mode < 0)
return this;
else
postComplete();
}
return null;
}
本文深入探讨了Java的CompletableFuture类,从任务初始化、后续处理操作到内部类的功能,如AsyncSupply、UniAccept等。通过源码分析,揭示了CompletableFuture如何封装任务、处理异步结果以及构建任务依赖。同时,详述了各关键方法的作用,如supplyAsync、thenAccept、tryFire等,帮助读者理解并发编程中的复杂交互。
517

被折叠的 条评论
为什么被折叠?



