completableFuture源码解析

本文详细解析了Java中的CompletableFuture类,重点讲解了uniApplyStage、postComplete、tryFire等核心方法,并通过实例解释了它们的工作原理。同时,介绍了Completion的模式async、sync和nested,帮助读者深入理解CompletableFuture的内部机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单解析image.png

首先尝试不看源码情况下讲清楚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
**/
  1. 首先cf1_1的completion入cf1的栈,成为栈顶 (以下都会把completion省略掉,直接写cf1_1)
  2. cf1_2入cf1的栈,成为栈顶,cf1栈内数据目前如下cf1_2->cf1_1
  3. cf1_2_1入cf1_2的栈
  4. cf1_2_2入cf1_2的栈,cf1_2栈内数据如下cf1_2_2->cf1_2_1
  5. 接下来执行cf1.complete,complete函数内执行postComplete
  6. 首先cf1_2出栈并执行,打印1_2
  7. h.tryFire因为cf1_2栈内非空,返回的是cf1_2的cf,此时f为cf1_2
  8. cf1_2出栈第一条为cf1_2_2,由于cf1_2_2后面还有cf1_2_1,所以把cf1_2_2入栈到cf1,此时cf1栈内数据cf1_2_2->cf1_1
  9. cf1_2出栈下一条为cf1_2_1,由于此时cf1_2栈内没有下一条了,直接执行cf1_2_1,不需要再入栈了,打印1_2_1
  10. cf1_2_1栈内为空,所以此时f为cf1_1
  11. 继续cf1_1出栈,栈顶为cf1_2_2,打印1_2_2
  12. 继续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出栈并且执行的,执行线程为出栈的那个线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值