CompletableFuture源码赏析

本文详细探讨了Java 1.8中的CompletableFuture类,它增强了Future接口,结合了Guava异步线程特性。文章分析了CompletableFuture的基本结构、属性及方法,如result、stack和Completion,并解释了如dependent和source等关键概念。示例中展示了单一使用和等待多个线程执行完成的场景。

文章原创,转载请注明出处:http://abc08010051.iteye.com/blog/2409693

后面会再修改一下,让文章读起来更好读,现在的版本还比较粗糙

 

 

CompletableFuture是java 1.8提供的一个新类,是对Future的增强,吸收了guava异步线程的特点,可以实现一系列的异步线程操作,很多常规的用法网上有很多博客,这里说说部分代码的实现:



  

这是CompletableFuture的基本结构

 

CompletableFuture基本属性方法

    volatile Object result;       // Either the result or boxed AltResult
    volatile Completion stack;    // Top of Treiber stack of dependent actions

result用来存放线程返回的结果

stack 行为上就是一个栈的功能,先进后出,用来存放要执行的动作,这个在单个异步线程返回时是没用的,多个线程等待的时候才排上用场

 

Completion基本属性方法

        volatile Completion next;      // Treiber stack link

        abstract CompletableFuture<?> tryFire(int mode);

 next链式结构,存放下一个

 tryFire 方法,主要返回一个依赖的Completion

 

名词解释:

dependent:依赖,多个线程操作时,如何等待每个线程都完成才返回,主要是依靠这个依赖,没处理完就会调用依赖的postComplete()方法向上传递

source:源,用户自定义的线程的CompletableFuture

 

 

1 单一使用

  

    /**
     * Returns a new CompletableFuture that is asynchronously completed
     * by a task running in the {@link ForkJoinPool#commonPool()} with
     * the value obtained by calling the given Supplier.
     *
     * @param supplier a function returning the value to be used
     * to complete the returned CompletableFuture
     * @param <U> the function's return type
     * @return the new CompletableFuture
     */
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
        return asyncSupplyStage(asyncPool, 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;
    }

    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句柄,把Supplier的返回值放到CompletableFuture的result属性中,当前线程的执行是在默认的线程池中执行,在外部可以获取
            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();
            }
        }
    }

  /**
     * Pops and tries to trigger all reachable dependents.  Call only
     * when known to be done.
     */
    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;
        //循环遍历CompletableFuture的stack属性,Completion是一个链式的操作,如果有下一个,触发下一个Completion的tryFire方法
        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;
            }
        }
    }

    

   等待获取结果

    

    public T get() throws InterruptedException, ExecutionException {
        Object r;
        return reportGet((r = result) == null ? waitingGet(true) : r);
    }


private Object waitingGet(boolean interruptible) {
        Signaller q = null;
        boolean queued = false;
        int spins = -1;
        Object r;
        //循环获取result属性,判断是否为空,不为空获取到结果,跳出while循环
        while ((r = result) == null) {
            if (spins < 0)
                //多个线程在允许,就给spins赋值256,然后循环递减,如果此时还没有返回值,则走下面的else分支
                spins = (Runtime.getRuntime().availableProcessors() > 1) ?
                    1 << 8 : 0; // Use brief spin-wait on multiprocessors
            else if (spins > 0) {
                if (ThreadLocalRandom.nextSecondarySeed() >= 0)
                    --spins;
            }
            else if (q == null)
                //创建等待信号线程
                q = new Signaller(interruptible, 0L, 0L);
            else if (!queued)
                //替换stack属性,把替换是否成功的结果赋值给queued
                queued = tryPushStack(q);
            else if (interruptible && q.interruptControl < 0) {//允许中断,并且q.interruptControl = 1,不会走此分支, 下面的循环出现出现线程中断会走此分支
                q.thread = null;
                cleanStack();
                return null;
            }
            else if (q.thread != null && result == null) {//如果结果没有返回,会进入当前分支
                try {
                    //循环判断q是否释放,等待一直到满足Signaller释放条件(主要判断是否超时),上面Signaller的构造方法中,deadline为0, 不会因为超时释放,只有线程中断的时候才会释放
                    ForkJoinPool.managedBlock(q);
                } catch (InterruptedException ie) {//如果发生线程中断,把Signaller的interruptControl置为-1,等到下一个循环使用
                    q.interruptControl = -1;
                }
            }
        }
        if (q != null) {//信号线程不为null, 如果Signaller的中断控制标记位小于0,则返回null或者线程中断
            q.thread = null;
            if (q.interruptControl < 0) {
                if (interruptible)
                    r = null; // report interruption
                else
                    Thread.currentThread().interrupt();
            }
        }
        //传递给下一个Completion,没有则不执行
        postComplete();
        return r;
    }


    private static <T> T reportGet(Object r)
        throws InterruptedException, ExecutionException {
        //根据不同的情况做返回值的包装
        if (r == null) // by convention below, null means interrupted
            throw new InterruptedException();
        if (r instanceof AltResult) {
            Throwable x, cause;
            if ((x = ((AltResult)r).ex) == null)
                return null;
            if (x instanceof CancellationException)
                throw (CancellationException)x;
            if ((x instanceof CompletionException) &&
                (cause = x.getCause()) != null)
                x = cause;
            throw new ExecutionException(x);
        }
        @SuppressWarnings("unchecked") T t = (T) r;
        return t;
    }
 

 

 2 等待多个线程执行完成再做返回

   

//demo , stageRunnable是一个实现Runnable类型的变量
CompletableFuture future = CompletableFuture.allOf(CompletableFuture.runAsync(stageRunnable),
            CompletableFuture.runAsync(stageRunnable), CompletableFuture.runAsync(stageRunnable));
        System.out.println(JSON.toJSONString(future));
        future.get();


    public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {
        return andTree(cfs, 0, cfs.length - 1);
    }

    //此方法是一个递归方法, 二分法把两个任务执行一个等待,每次二分都会创建一个CompletableFuture的depency
    static CompletableFuture<Void> andTree(CompletableFuture<?>[] cfs,
                                           int lo, int hi) {
        CompletableFuture<Void> d = new CompletableFuture<Void>();
        if (lo > hi) // empty
            d.result = NIL;
        else {
            CompletableFuture<?> a, b;
            int mid = (lo + hi) >>> 1;
            if ((a = (lo == mid ? cfs[lo] :
                      andTree(cfs, lo, mid))) == null ||
                (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
                      andTree(cfs, mid+1, hi)))  == null)
                throw new NullPointerException();
            if (!d.biRelay(a, b)) {//a,b两个子任务没有全部完成,走此分支
                BiRelay<?,?> c = new BiRelay<>(d, a, b);//创建一个Completion,一个依赖,两个source
                a.bipush(b, c);//把c推送到a,b的stack属性当中去
                c.tryFire(SYNC);//BiRelay触发实际操作
            }
        }
        return d;
    }

    //根据方法名直译的意思:是否两个传播都已经完成;两个任务有任何一个未完成,则返回false, 只有全部完成的时候才会返回true
    boolean biRelay(CompletableFuture<?> a, CompletableFuture<?> b) {
        Object r, s; Throwable x;
        if (a == null || (r = a.result) == null ||
            b == null || (s = b.result) == null)
            return false;
        if (result == null) {
            if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
                completeThrowable(x, r);
            else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null)
                completeThrowable(x, s);
            else
                completeNull();
        }
        return true;
    }
    
 
   等待多个线程结束是怎么等待的呢?
 
    //关于这个方法上面每个步骤都有注释,这里只写关键部分
    private Object waitingGet(boolean interruptible) {
        Signaller q = null;
        boolean queued = false;
        int spins = -1;
        Object r;
        while ((r = result) == null) {
            if (spins < 0)
                spins = (Runtime.getRuntime().availableProcessors() > 1) ?
                    1 << 8 : 0; // Use brief spin-wait on multiprocessors
            else if (spins > 0) {
                if (ThreadLocalRandom.nextSecondarySeed() >= 0)
                    --spins;
            }
            else if (q == null)
                q = new Signaller(interruptible, 0L, 0L);
            else if (!queued)
                //创建一个信号线程,并推送到Completable的stack属性中,等到线程执行完的时候会执行CompletableFuture这个依赖的Completion
                //即当前的Signaller类型的q,请看下面源码signal的tryFire方法实现
                queued = tryPushStack(q);
            else if (interruptible && q.interruptControl < 0) {
                q.thread = null;
                cleanStack();
                return null;
            }
            else if (q.thread != null && result == null) {
                try {
                    //调用Signaller的block和isReleasable方法,无法获取到结果的时候会被阻塞,看下面block具体的代码
                    ForkJoinPool.managedBlock(q);
                } catch (InterruptedException ie) {
                    q.interruptControl = -1;
                }
            }
        }
        if (q != null) {
            q.thread = null;
            if (q.interruptControl < 0) {
                if (interruptible)
                    r = null; // report interruption
                else
                    Thread.currentThread().interrupt();
            }
        }
        postComplete();
        return r;
    }
      
       //Signaller的block方法
       public boolean block() {
            if (isReleasable())
                return true;
            else if (deadline == 0L)//执行到此步时,线程会阻塞
                LockSupport.park(this);
            else if (nanos > 0L)
                LockSupport.parkNanos(this, nanos);
            return isReleasable();
        }

        //Signaller类的tryFire方法
        final CompletableFuture<?> tryFire(int ignore) {
            Thread w; // no need to atomically claim
            if ((w = thread) != null) {
                thread = null;
		//最重要的方法,对当前线程执行了一个unpark方法,此方法会在所有的任务线程执行完了之后,执行postComplete()方法时调用,
		//唤醒因为无法获取计算结果而阻塞的当前线程
                LockSupport.unpark(w);
            }
            return null;
        }

  

 

### Java CompletableFuture 源码解析 `CompletableFuture` 是 Java 8 引入的一个强大工具,用于支持异步编程和回调机制。它是 `Future` 接口的扩展版本,提供了更丰富的功能来简化复杂的异步操作链式调用。 #### 1. 基本结构与设计思路 `CompletableFuture` 的核心设计理念基于状态机模型[^3]。它的内部维护了一个复杂的状态转换逻辑,允许开发者通过一系列方法(如 `supplyAsync`, `thenApply`, `whenComplete` 等)构建异步任务流水线。这些方法本质上是对底层状态的变化进行监听并触发相应的动作。 以下是其主要组成部分: - **内部类**:`CompletableFuture` 定义了许多嵌套类,比如 `UniCompletion`, `BiCompletion` 和 `AsynchronousCompletionTask` 等,用来管理不同类型的依赖关系。 - **原子变量**:利用 `AtomicReferenceFieldUpdater` 或者类似的低级同步原语确保多线程环境下的安全性。 - **完成器 (Completor)** :当某个阶段的任务完成后,会通知后续阶段继续执行。 #### 2. 关键方法分析 ##### a. 创建实例 可以通过静态工厂方法创建新的未完成实例或者已经完成了计算结果的实例: ```java // 返回一个新的已完成的 CompletableFuture 对象 static <U> CompletableFuture<U> completedFuture(U value); ``` 此方法直接返回带有指定值的结果对象而无需实际运行任何异步任务[^4]。 ##### b. 提交任务 提交一个供给型任务给默认 ForkJoinPool 执行,并返回代表该未来结果的新 CompletableFuture 实例: ```java public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier); ``` 如果希望自定义 Executor,则可以使用重载版函数传递第二个参数作为定制化的线程池[^1]: ```java public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor); ``` ##### c. 链接下游处理器 一旦前序步骤结束就可以无缝衔接下一个处理单元形成完整的数据流管道图谱。例如下面这段代码展示了如何串联两个独立的操作序列: ```java CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // Task A: Simulate some work... return "Result from TaskA"; }).thenApply(resultFromPreviousStep -> { // Task B: Process the result of previous step. String processedData = process(resultFromPreviousStep); return processedData; }); ``` 这里 `.thenApply()` 方法接收的是 Function 类型泛型参数形式化表达映射变换规则从而实现从输入到输出之间的转化过程。 #### 3. 并发控制细节 为了提高性能表现以及减少不必要的上下文切换开销,在某些特定场景下可能会采用 inline 方式即时求解而不是真正启动新线程去完成整个流程。这种行为取决于当前所处模式(`mode`)设置情况——即是否处于 nested 模式之下[^5]。 具体来说,当检测到存在可用资源时便会尝试立即履行承诺;反之则遵循常规调度策略安排至适当位置等待时机成熟后再予以兑现。 --- ### 示例代码展示 以下是一个综合运用上述知识点的例子演示了如何组合多个异步操作最终达成目标效果的同时保持良好的可读性和模块划分清晰度: ```java import java.util.concurrent.CompletableFuture; public class CompletableFutureExample { public static void main(String[] args) throws Exception { CompletableFuture<Integer> cf = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(100); } catch (InterruptedException e) {} System.out.println("Supplying..."); return 123; }).thenApply(i -> { System.out.println("Applying transformation..."); return i * 2; }); Integer result = cf.join(); // Blocks until complete System.out.println("Final Result: " + result); } } ``` 在此程序片段里我们首先发起了一项耗时较长的基础服务请求随后对其响应内容加以进一步加工最后打印出总的运算成果。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值