CompletableFuture源码分析
接口设计
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
CompletableFuture实现了Future接口和CompletionStage接口。
Future接口可以方便的获取多线程异步执行时的结果,当线程异步执行结束之后,返回的结果将会保存在Future中。
CompletionStage接口代表了一个异步执行的动作阶段,当执行完一个动作阶段后会返回新的CompletionStage,通过CompletionStage可以关联成链式结构。
CompletionStage接口
一个阶段的执行计算可以通过调用Function接口, Consumer接口 或 Runnable接口去实现。其中包含有同步执行,异步执行(Async)和指定异步执行的线程池(Executor)。
Function接口:
public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn); public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn); public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn,Executor executor); public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn); ...
Consumer接口:
public CompletionStage<Void> thenAccept(Consumer<? super T> action); public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action); public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor); public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action); ...
Runnable接口:
public CompletionStage<Void> thenRun(Runnable action); public CompletionStage<Void> thenRunAsync(Runnable action); public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor); public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action); ...
一个阶段的执行可以在上一个阶段,或者多个阶段,或者多个阶段中的任何一个阶段执行完成后执行
结构设计
volatile Object result; // Either the result or boxed AltResult volatile Completion stack; // Top of Treiber stack of dependent actions
CompletableFuture 由 result(当前计算结果),stack(Completion通过链表实现栈来记录当前计算完成后需要触发的依赖动作)组成
CompletableFuture<String> completableFuture =
CompletableFuture.supplyAsync(() -> "stage one").thenApplyAsync(s -> s + " stage two");
上面示例中第二个任务的执行依赖第一个任务的执行结果,我们通过分析supplyAsync 和thenApplyAsync方法来理解CompletableFuture的运行实现原理
supplyAsync
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) { return asyncSupplyStage(asyncPool, supplier); }
asyncPool为ForkJoinPool.commonPool()默认线程池,supplier为需要执行的任务逻辑
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; }
Executor e不指定线程池时为ForkJoinPool.commonPool()默认线程池,若通过supplyAsync(Supplier<U> supplier,Executor executor)指定特定线程池时为我们此时传入的线程池,此时在执行任务前通过包装为AsyncSupply来执行任务
static final class AsyncSupply<T> extends ForkJoinTask<Void> implements Runnable, AsynchronousCompletionTask { CompletableFuture<T> dep; Supplier<T> fn; AsyncSupply(CompletableFuture<T> dep, Supplier<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 true; } public void run() { CompletableFuture<T> d; Supplier<T> f; if ((d = dep) != null && (f = fn) != null) { dep = null; fn = null; //若任务已执行完成就不再执行 if (d.result == null) { try { d.completeValue(f.get()); } catch (Throwable ex) { d.completeThrowable(ex); } } d.postComplete(); } } }
AsyncSupply继承了ForkJoinTask,实现了Runnable保证既可以执行默认ForkJoinPool.commonPool()又可以执行自定义的线程池。f.get()开始执行任务逻辑,completeValue方法将执行的结果通过CAS方式设置到result中,之后通过postComplete执行后续动作
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 (f.casStack(h, t = h.next)) { if (t != null) { if (f != this) { pushStack(h); continue; } h.next = null; // detach } f = (d = h.tryFire(NESTED)) == null ? this : d; } } }
postComplete中若stack栈顶元素不为空,取到stack栈顶元素,f.casStack(h, t = h.next)通过CAS将栈顶指针后移,执行栈中的每个Completion的tryFire方法,若Completion的tryFire方法返回了另外的CompletableFuture,并且另外的CompletableFuture中的stack不为空,会逐个将stack中的Completion压入原CompletableFuture的栈中。当原CompletableFuture对象Completion栈中所有引用的CompletableFuture中的Completion都压入原CompletableFuture栈后,原CompletableFuture就会依次执行栈中Completion的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 true; } public final Void getRawResult() { return null; } public final void setRawResult(Void v) {} }
Completion中tryFire为定义的模板抽象方法,可以通过三种模式执行:SYNC(同步模式),ASYNC(异步模式),NESTED(嵌套模式)
thenApplyAsync
public <U> CompletableFuture<U> thenApplyAsync( Function<? super T,? extends U> fn) { return uniApplyStage(asyncPool, fn); }
private <V> CompletableFuture<V> uniApplyStage( Executor e, Function<? super T,? extends V> f) { if (f == null) throw new NullPointerException(); CompletableFuture<V> d = new CompletableFuture<V>(); if (e != null || !d.uniApply(this, f, null)) { UniApply<T,V> c = new UniApply<T,V>(e, d, this, f); push(c); c.tryFire(SYNC); } return d;
同步执行时Executor e为null,异步执行会传入线程池。thenApplyAsync在异步执行时为ForkJoinPool.commonPool()线程池,之后尝试将包装的UniApply压入原CompletableFuture栈中,此时原CompletableFuture有可能任务已经执行完成(此时压栈失败),所以需要执行UniApply类实现的tryFire方法
final CompletableFuture<V> tryFire(int mode) { CompletableFuture<V> d; CompletableFuture<T> a; if ((d = dep) == null || !d.uniApply(a = src, fn, mode > 0 ? null : this)) return null; dep = null; src = null; fn = null; return d.postFire(a, mode); }
tryFire方法中执行uniApply方法,uniApply中当前CompletableFuture任务若执行完成,返回true,执行下面的postFire方法
final <S> boolean uniApply(CompletableFuture<S> a, Function<? super S,? extends T> f, UniApply<S,T> c) { Object r; Throwable x; if (a == null || (r = a.result) == null || f == null) return false; tryComplete: if (result == null) { if (r instanceof AltResult) { if ((x = ((AltResult)r).ex) != null) { completeThrowable(x, r); break tryComplete; } r = null; } try { if (c != null && !c.claim()) return false; @SuppressWarnings("unchecked") S s = (S) r; completeValue(f.apply(s)); } catch (Throwable ex) { completeThrowable(ex); } } return true; }
CompletableFuture<S> a为原CompletableFuture,若原CompletableFuture的任务已经执行完成,当前CompletableFuture的任务还未完成, 在原CompletableFuture执行成功的情况下执行当前CompletableFuture的任务,执行成功后返回ture
final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) { if (a != null && a.stack != null) { if (mode < 0 || a.result == null) a.cleanStack(); else a.postComplete(); } if (result != null && stack != null) { if (mode < 0) return this; else postComplete(); } return null; }
postFire方法中a为原CompletableFuture,mode为具体模式 SYNC(同步模式:0),ASYNC(异步模式:1),NESTED(嵌套模式:-1)。若为嵌套执行模式(mode<0),或原CompletableFuture任务未执行完成(a.result == null),执行cleanStack方法(将栈中无效的Completion清除掉),其它情况执行postComplete方法。若当前CompletableFuture任务已经执行完成(result != null),并且栈中有要执行的Completion(stack != null),且为嵌套模式时(mode < 0),返回该对象本身(后续由外部postComplete执行),其它模式直接执行postComplete。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?