最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?CompletableFuture實(shí)現(xiàn)原理分析詳解

 更新時(shí)間:2022年09月30日 14:34:24   作者:生命猿于運(yùn)動(dòng)  
CompletableFuture是Java8并發(fā)新特性,本文我們主要來(lái)聊一聊CompletableFuture的回調(diào)功能以及異步工作原理是如何實(shí)現(xiàn)的,需要的可以了解一下

簡(jiǎn)介

前面的一篇文章你知道Java8并發(fā)新特性CompletableFuture嗎?介紹了CompletableFuture的特性以及一些使用方法,今天我們主要來(lái)聊一聊CompletableFuture的回調(diào)功能以及異步工作原理是如何實(shí)現(xiàn)的。

CompletableFuture類(lèi)結(jié)構(gòu)

1.CompletableFuture類(lèi)結(jié)構(gòu)主要有兩個(gè)屬性

public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
    volatile Object result;       // Either the result or boxed AltResult
    volatile Completion stack;    // Top of Treiber stack of dependent actions
    ...
}
  • result:存儲(chǔ)CompletableFuture的返回,或者存儲(chǔ)異常對(duì)象AltResult。
  • stack:是CompletableFuture.Completion對(duì)象,表示操作數(shù)棧棧頂,在進(jìn)行CompletableFuture鏈?zhǔn)秸{(diào)用的過(guò)程中,所有鏈?zhǔn)秸{(diào)用的CompletableFuture任務(wù)都會(huì)被壓入該stack中,在任務(wù)調(diào)用的過(guò)程按后進(jìn)先出的順序出棧執(zhí)行完所有任務(wù)。

2.stack屬性棧結(jié)構(gòu)

abstract static class Completion extends ForkJoinTask<Void>
    implements Runnable, AsynchronousCompletionTask {
    volatile Completion next;      // Treiber stack link
    ...
}

next:存儲(chǔ)下一個(gè)任務(wù)鏈?zhǔn)秸{(diào)用棧。

3.UniCompletion的內(nèi)部結(jié)構(gòu)

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繼承Completion類(lèi),包含以下幾個(gè)參數(shù):

  • executor:異步任務(wù)執(zhí)行器,如果為空則有主線(xiàn)程執(zhí)行任務(wù)不進(jìn)行異步執(zhí)行。
  • dep:指向當(dāng)前任務(wù)構(gòu)建的CompletabueFuture
  • src:指向源CompletableFuture任務(wù)

CompletableFuture回調(diào)原理

這里為了方便講解,我們用以下簡(jiǎn)短的代碼來(lái)進(jìn)行分析:

public static void main(String[] args) {
    CompletableFuture<String> baseFuture = CompletableFuture.completedFuture("Base Future");
    log.info(baseFuture.thenApply((r) -> r + " Then Apply").join());
    baseFuture.thenAccept((r) -> log.info(r)).thenAccept((Void) -> log.info("Void"));
}

上面的代碼我們通過(guò)創(chuàng)建一個(gè)簡(jiǎn)單的CompletableFuture對(duì)象,再執(zhí)行baseFuture.thenApply()調(diào)用后會(huì)進(jìn)行一個(gè)入棧操作,如下圖baseFuture引用的CompletableFuturestack屬性將會(huì)指向baseFuture.thenApply()結(jié)果返回的新CompletableFuture對(duì)象,而新CompletableFuture對(duì)象的src屬性將指向來(lái)源CompletableFuturebaseFuture所引用的對(duì)象。

2.在上一步的基礎(chǔ)上再執(zhí)行下一行代碼,結(jié)果的引用關(guān)系圖如下圖:

在執(zhí)行完baseFuture.thenAccept()的時(shí)候,thenAccept返回的任務(wù)將被壓入棧頂,next指向上一個(gè)代碼段的返回對(duì)象,在thenAccept返回的新CompletableFuture對(duì)象中在進(jìn)行一次thenAccept的調(diào)用,就再產(chǎn)生一個(gè)新的CompletableFuture對(duì)象,dept屬性就指向最新的CompletableFuture對(duì)象。

thenApply實(shí)現(xiàn)源碼分析

public <U> CompletableFuture<U> thenApply(
    Function<? super T,? extends U> fn) {
    return uniApplyStage(null, fn);
}

private <V> CompletableFuture<V> uniApplyStage(
    Executor e, Function<? super T,? extends V> f) {
    if (f == null) throw new NullPointerException();
    // 創(chuàng)建一個(gè)新的CompletableFuture對(duì)象
    CompletableFuture<V> d =  new CompletableFuture<V>();
    // e:如果是異步調(diào)用直接執(zhí)行代碼塊
    // !d.uniApply:執(zhí)行任務(wù),如果返回false則任務(wù)未執(zhí)行需入棧
    if (e != null || !d.uniApply(this, f, null)) {
        UniApply<T,V> c = new UniApply<T,V>(e, d, this, f);
        // 創(chuàng)建出新的UniApply對(duì)象進(jìn)行入棧
        push(c);
        // 嘗試執(zhí)行任務(wù)
        c.tryFire(SYNC);
    }
    return d;
}

final <S> boolean uniApply(CompletableFuture<S> a,
                           Function<? super S,? extends T> f,
                           UniApply<S,T> c) {
    Object r; Throwable x;
    // 任務(wù)未完成結(jié)果為null直接返回false
    if (a == null || (r = a.result) == null || f == null)
        return false;
    // 驗(yàn)證是否出現(xiàn)異常結(jié)果,如有則任務(wù)執(zhí)行結(jié)束
    tryComplete: if (result == null) {
        if (r instanceof AltResult) {
            if ((x = ((AltResult)r).ex) != null) {
                completeThrowable(x, r);
                break tryComplete;
            }
            r = null;
        }
        try {
            // 異步執(zhí)行任務(wù)
            if (c != null && !c.claim())
                // 任務(wù)未執(zhí)行返回false
                return false;
            @SuppressWarnings("unchecked") S s = (S) r;
            // 任務(wù)執(zhí)行完成將結(jié)果寫(xiě)入result
            completeValue(f.apply(s));
        } catch (Throwable ex) {
            completeThrowable(ex);
        }
    }
    return true;
}

以上代碼片段主要描述了CompletableFuture在執(zhí)行任務(wù)時(shí)會(huì)創(chuàng)建出新的CompletableFuture對(duì)象,使用新對(duì)象執(zhí)行任務(wù)并獲取結(jié)果使用CAS寫(xiě)入到result屬性,如果任務(wù)未執(zhí)行將壓入棧頂,再重新嘗試任務(wù)執(zhí)行,在CompletableFuture其他方法的調(diào)用也都大同小異,這里不在逐一分析,可自行打開(kāi)源碼閱讀便于理解。

CompletableFuture異步原理

需要進(jìn)行CompletableFuture異步調(diào)用則要使用Async結(jié)尾的方法執(zhí)行任務(wù),這里我們就拿thenAcceptAsync()的源碼進(jìn)行分析。

public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {
    return uniAcceptStage(asyncPool, action);
}

private CompletableFuture<Void> uniAcceptStage(Executor e, Consumer<? super T> f) {
    if (f == null) throw new NullPointerException();
    CompletableFuture<Void> d = new CompletableFuture<Void>();
    // 如果是異步任務(wù),這里的參數(shù)e不會(huì)為空,也就是會(huì)將任務(wù)執(zhí)行壓入棧頂
    if (e != null || !d.uniAccept(this, f, null)) {
        UniAccept<T> c = new UniAccept<T>(e, d, this, f);
        push(c);
        // 重點(diǎn)還是這個(gè)入口
        c.tryFire(SYNC);
    }
    return d;
}

static final class UniAccept<T> extends UniCompletion<T,Void> {
    Consumer<? super T> 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;
        // dep為空即任務(wù)已被執(zhí)行過(guò),直接返回null
        // uniAccept()結(jié)果為false,可能是任務(wù)執(zhí)行中未完成,也可能是由線(xiàn)程池中的其他任務(wù)執(zhí)行完成
        if ((d = dep) == null || !d.uniAccept(a = src, fn, mode > 0 ? null : this))
            return null;
        dep = null; src = null; fn = null;
        // 說(shuō)明當(dāng)前線(xiàn)程執(zhí)行了該任務(wù),返回結(jié)果繼續(xù)執(zhí)行前一個(gè)任務(wù)
        return d.postFire(a, mode);
    }
}

final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
    if (a != null && a.stack != null) {
        // postComplete調(diào)用過(guò)來(lái)的,或者上一個(gè)任務(wù)執(zhí)行完成,清空棧數(shù)據(jù),否則調(diào)用postComplete完成任務(wù)
        if (mode < 0 || a.result == null)
            a.cleanStack();
        else
            // 完成任務(wù)執(zhí)行并進(jìn)行出棧
            a.postComplete();
    }
    if (result != null && stack != null) {
        if (mode < 0)
            // postComplete調(diào)用過(guò)來(lái)的任務(wù)已完成
            return this;
        else
            // 完成任務(wù)執(zhí)行并進(jìn)行出棧
            postComplete();
    }
    return null;
}

CompletableFuture進(jìn)行異步主要是通過(guò)將任務(wù)壓入棧頂后tryFire方法進(jìn)行異步處理,如果任務(wù)未被執(zhí)行則會(huì)通過(guò)postFire方法有線(xiàn)程池中的線(xiàn)程進(jìn)行任務(wù)執(zhí)行,任務(wù)執(zhí)行結(jié)果再使用CAS將結(jié)果返回到result,其他線(xiàn)程即可得知任務(wù)是否被執(zhí)行過(guò),如果當(dāng)前現(xiàn)場(chǎng)判斷當(dāng)前任務(wù)為被執(zhí)行,則調(diào)用postComplete()執(zhí)行完成任務(wù)。

總結(jié)

CompletableFuture通過(guò)異步回調(diào)的方式,解決了開(kāi)發(fā)過(guò)程中異步調(diào)用獲取結(jié)果的難點(diǎn)。開(kāi)發(fā)人員只需接觸到CompletableFuture對(duì)象,以及CompletableFuture任務(wù)的執(zhí)行結(jié)果,無(wú)需設(shè)計(jì)具體異步回調(diào)的實(shí)現(xiàn),并可通過(guò)自定義線(xiàn)程池進(jìn)一步優(yōu)化任務(wù)的異步調(diào)用。

到此這篇關(guān)于Java CompletableFuture實(shí)現(xiàn)原理分析詳解的文章就介紹到這了,更多相關(guān)Java CompletableFuture內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

汉寿县| 沾益县| 德保县| 太原市| 永昌县| 石狮市| 兖州市| 康保县| 吴桥县| 新河县| 玉树县| 资兴市| 五常市| 应用必备| 阿尔山市| 喀喇沁旗| 新河县| 阿拉尔市| 台江县| 青浦区| 锡林浩特市| 沙雅县| 漯河市| 乌兰察布市| 廊坊市| 轮台县| 泸州市| 南康市| 灵武市| 黄骅市| 廉江市| 庆安县| 海南省| 花莲市| 黄浦区| 龙海市| 竹山县| 德庆县| 大英县| 奉节县| 龙里县|