一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Java 8 的異步利器:CompletableFuture源碼級(jí)解析(建議精讀)

 昵稱(chēng)10087950 2022-08-21 發(fā)布于江蘇

日英文

Life is like a one way street, none of them leads back. So enjoy the right moment as none of them will happen again.

人生就像一條單行道,一去不復(fù)返。既然一切無(wú)法回頭,就讓我們好好享受此刻吧!

每日掏心話(huà)

每一次選擇必須是一次超越,否則就不要選擇;每一次放棄必須是一次升華,否則就不要放棄。

責(zé)編:樂(lè)樂(lè) | 來(lái)自:blog.csdn.net/finalheart/article/details/87615546

  正文   

  大家好,我是小樂(lè)。

completableFuture是JDK1.8版本新引入的類(lèi)。下面是這個(gè)類(lèi):

圖片

實(shí)現(xiàn)了倆接口,本身是個(gè)class。這個(gè)是Future的實(shí)現(xiàn)類(lèi),使用completionStage接口去支持完成時(shí)觸發(fā)的函數(shù)和操作。

一個(gè)completetableFuture就代表了一個(gè)任務(wù),他能用Future的方法,還能做一些之前說(shuō)的executorService配合futures做不了的。

之前future需要等待isDone為true才能知道任務(wù)跑完了,或者就是用get方法調(diào)用的時(shí)候會(huì)出現(xiàn)阻塞,而使用completableFuture的使用就可以用then,when等等操作來(lái)防止以上的阻塞和輪詢(xún)isDone的現(xiàn)象出現(xiàn)。


1.創(chuàng)建CompletableFuture直接new對(duì)象。

一個(gè)completableFuture對(duì)象代表著一個(gè)任務(wù),這個(gè)對(duì)象能跟這個(gè)任務(wù)產(chǎn)生聯(lián)系。

下面用的complete方法意思就是這個(gè)任務(wù)完成了需要返回的結(jié)果,然后用get()方法可以獲取到。


圖片

2.JDK1.8使用的接口類(lèi)。

在本文的CompletableFuture中大量的使用了這些函數(shù)式接口。

注:這些聲明大量應(yīng)用于方法的入?yún)⒅校?code>thenApply和thenAccept這倆就是一個(gè)用Function一個(gè)用Consumer

而lambda函數(shù)正好是可以作為這些接口的實(shí)現(xiàn)。例如 s->{return 1;} 這個(gè)就相當(dāng)于一個(gè)Function。因?yàn)橛腥雲(yún)⒑头祷亟Y(jié)果。

圖片(1)Function

圖片(2)Consumer

圖片對(duì)于前面有Bi的就是這樣的,BiConsumer就是兩個(gè)參數(shù)的。

圖片(3)Predicate這個(gè)接口聲明是一個(gè)入?yún)?,返回一個(gè)boolean。

圖片(4)supplier

圖片

3.下面是這個(gè)類(lèi)的靜態(tài)方法

帶有Async就是異步執(zhí)行的意思、也是一個(gè)completableFuture對(duì)象代表著一個(gè)任務(wù)這個(gè)原則。

這種異步方法都可以指定一個(gè)線(xiàn)程池作為任務(wù)的運(yùn)行環(huán)境,如果沒(méi)有指定就會(huì)使用ForkJoinPool線(xiàn)程池來(lái)執(zhí)行

圖片(1)supplyAsync&runAsync的使用例子。

public static void main(String[] args) throws ExecutionException, InterruptedException {
    ExecutorService executorService = Executors.newCachedThreadPool();
    executorService.submit(new Callable<Object>() {
        @Override
        public Object call() throws Exception {
            System.out.println('executorService 是否為守護(hù)線(xiàn)程 :' + Thread.currentThread().isDaemon());
            return null;
        }
    });
    final CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
        System.out.println('this is lambda supplyAsync');
        System.out.println('supplyAsync 是否為守護(hù)線(xiàn)程 ' + Thread.currentThread().isDaemon());
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println('this lambda is executed by forkJoinPool');
        return 'result1';
    });
    final CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        System.out.println('this is task with executor');
System.out.println('supplyAsync 使用executorService 時(shí)是否為守護(hù)線(xiàn)程 : ' + Thread.currentThread().isDaemon());
        return 'result2';
    }, executorService);
    System.out.println(completableFuture.get());
    System.out.println(future.get());
    executorService.shutdown();
}

圖片這些任務(wù)中帶有supply是持有返回值的,run是void返回值的,在玩supply時(shí)發(fā)現(xiàn)一個(gè)問(wèn)題:如果使用supplyAsync任務(wù)時(shí)不使用任務(wù)的返回值,即不用get方法阻塞主線(xiàn)程會(huì)導(dǎo)致任務(wù)執(zhí)行中斷。

注:跟get方法無(wú)關(guān),后面有答案

圖片圖片然后我開(kāi)始探索是否是只有supplyAsync是這樣。我測(cè)試了runAsync發(fā)現(xiàn)也是這樣。

圖片下圖為與supplyAsync任務(wù)執(zhí)行不全面一樣的問(wèn)題,我甚至測(cè)試了將lambda換成runnable發(fā)現(xiàn)無(wú)濟(jì)于事。另外,搜索公眾號(hào)GitHub猿后臺(tái)回復(fù)“賺錢(qián)”,獲取一份驚喜禮包。

圖片

答案:

造成這個(gè)原因是因?yàn)镈aemon。因?yàn)?code>completableFuture這套使用異步任務(wù)的操作都是創(chuàng)建成了守護(hù)線(xiàn)程,那么我們沒(méi)有調(diào)用get方法不阻塞這個(gè)主線(xiàn)程的時(shí)候。主線(xiàn)程執(zhí)行完畢,所有線(xiàn)程執(zhí)行完畢就會(huì)導(dǎo)致一個(gè)問(wèn)題,就是守護(hù)線(xiàn)程退出。

那么我們沒(méi)有執(zhí)行的代碼就是因?yàn)橹骶€(xiàn)程不再跑任務(wù)而關(guān)閉導(dǎo)致的,可能這個(gè)不叫問(wèn)題,因?yàn)樵陂_(kāi)發(fā)中我們主線(xiàn)程常常是一直開(kāi)著的。但是這個(gè)小問(wèn)題同樣讓我想了好久。

下面我們開(kāi)一個(gè)非守護(hù)線(xiàn)程,可以看到程序執(zhí)行順利。

圖片下面證實(shí)守護(hù)線(xiàn)程在其他非守護(hù)線(xiàn)程全部退出的情況下不繼續(xù)執(zhí)行。

final CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
    System.out.println('this is lambda supplyAsync');
    System.out.println('supplyAsync 是否為守護(hù)線(xiàn)程 ' + Thread.currentThread().isDaemon());
    try {
        TimeUnit.SECONDS.sleep(1);
        try(BufferedWriter writer = new BufferedWriter
                (new OutputStreamWriter(new FileOutputStream(new File('/Users/zhangyong/Desktop/temp/out.txt'))))){
            writer.write('this is completableFuture daemon test');
        }catch (Exception e){
            System.out.println('exception find');
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println('this lambda is executed by forkJoinPool');
    return 'result1';
});

這個(gè)代碼就是操作本地文件,并且sleep了一秒。其他線(xiàn)程就一句控制臺(tái)輸出的代碼,最終的結(jié)果是文件沒(méi)有任何變化。

當(dāng)我把主線(xiàn)程sleep 5秒時(shí),本地文件會(huì)寫(xiě)入一句  this is completableFuture daemon test   驗(yàn)證成功。

(2)allOf&anyOf

這兩個(gè)方法的入?yún)⑹且粋€(gè)completableFuture組、allOf就是所有任務(wù)都完成時(shí)返回,但是是個(gè)Void的返回值。

anyOf是當(dāng)入?yún)⒌?code>completableFuture組中有一個(gè)任務(wù)執(zhí)行完畢就返回,返回結(jié)果是第一個(gè)完成的任務(wù)的結(jié)果。

public static void otherStaticMethod() throws ExecutionException, InterruptedException {
        final CompletableFuture<String> futureOne = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                System.out.println('futureOne InterruptedException');
            }
            return 'futureOneResult';
        });
        final CompletableFuture<String> futureTwo = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                System.out.println('futureTwo InterruptedException');
            }
            return 'futureTwoResult';
        });
        CompletableFuture future = CompletableFuture.allOf(futureOne, futureTwo);
        System.out.println(future.get());
//        CompletableFuture completableFuture = CompletableFuture.anyOf(futureOne, futureTwo);
//        System.out.println(completableFuture.get());
    }

圖片圖片(3)completedFuture這個(gè)方法我沒(méi)懂他是干啥的,源碼就是返回一個(gè)值。感覺(jué)沒(méi)啥意義。

圖片(4)取值方法,除了get還有一個(gè)getNow(); 這個(gè)就比較特殊了。

這個(gè)方法是執(zhí)行這個(gè)方法的時(shí)候任務(wù)執(zhí)行完了就返回任務(wù)的結(jié)果,如果任務(wù)沒(méi)有執(zhí)行完就返回你的入?yún)ⅰ?/p>

圖片(5)join方法跟線(xiàn)程的join用法差不多。

圖片(6)whenXXX,在一個(gè)任務(wù)執(zhí)行完成之后調(diào)用的方法。

這個(gè)有三個(gè)名差不多的方法:whenComplete、whenCompleteAsync、還有一個(gè)是whenCompleteAsync用自定義Executor

圖片首先看一下這個(gè)whenComplete實(shí)例方法。這個(gè)就是任務(wù)執(zhí)行完畢調(diào)用的,傳入一個(gè)action,這個(gè)方法的執(zhí)行線(xiàn)程是當(dāng)前線(xiàn)程,意味著會(huì)阻塞當(dāng)前線(xiàn)程。

下面圖中test的輸出跟whenComplete方法運(yùn)行的線(xiàn)程有關(guān),運(yùn)行到main線(xiàn)程就會(huì)阻塞test的輸出,運(yùn)行的是completableFuture線(xiàn)程則不會(huì)阻塞住test的輸出。

圖片下面是任務(wù)執(zhí)行的線(xiàn)程的探索。

圖片圖片圖片圖片圖片圖片

牛逼?。〗铀交畋貍涞?N 個(gè)開(kāi)源項(xiàng)目!趕快收藏吧

圖片圖片根據(jù)測(cè)試得出的結(jié)論是:如果調(diào)用whenComplete的中途,還發(fā)生了其他事情,圖中的主線(xiàn)程的sleep(400);導(dǎo)致completableFuture這個(gè)任務(wù)執(zhí)行完畢了,那么就使用主線(xiàn)程調(diào)用。

如果調(diào)用的中途沒(méi)有發(fā)生其他任務(wù)且在觸碰到whenComplete方法時(shí)completableFuture這個(gè)任務(wù)還沒(méi)有徹底執(zhí)行完畢那么就會(huì)用completableFuture這個(gè)任務(wù)所使用的線(xiàn)程。

下面是whenCompleteAsync方法。這個(gè)方法就是新創(chuàng)建一個(gè)異步線(xiàn)程執(zhí)行。所以不會(huì)阻塞。

圖片(7) then方法瞅著挺多的,實(shí)際上就是異不異步和加不加自定義Executor

圖片

注:whenComplete中出現(xiàn)的問(wèn)題在then中測(cè)試不存在、使用的就是上一個(gè)任務(wù)的線(xiàn)程。這個(gè)thenCompose就是一個(gè)任務(wù)執(zhí)行完之后可以用它的返回結(jié)果接著執(zhí)行的方法,方法返回的是另一個(gè)你期盼泛型的結(jié)果。

compose理解就是上一個(gè)任務(wù)結(jié)果是then的一部分。

圖片下面介紹一下thenCombine

這個(gè)combine的理解就是結(jié)合兩個(gè)任務(wù)的結(jié)果。

圖片綜上:這個(gè)線(xiàn)程的問(wèn)題并不是大問(wèn)題,只要你不用線(xiàn)程來(lái)做判斷條件,他并不會(huì)影響你的效率。試想pool線(xiàn)程都執(zhí)行完了就用主線(xiàn)程跑唄。沒(méi)跑完,而使你等了那你就用pool線(xiàn)程唄。

thenRun就是這個(gè)任務(wù)運(yùn)行完,再運(yùn)行下一個(gè)任務(wù),感覺(jué)像是join了一下。

圖片其余不再介紹,大同小異。

thenApply(Function);這樣的就是有入?yún)⒂蟹祷刂殿?lèi)型的。

thenAccept(Consumer);這樣的就是有入?yún)?,但是沒(méi)有返回值的。詳情在上文中有過(guò)關(guān)于函數(shù)式接口的敘述。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多

    国产精品伦一区二区三区四季 | 美国欧洲日本韩国二本道| 日本成人三级在线播放| 日本东京热加勒比一区二区| 午夜精品一区二区三区国产| 国产老女人性生活视频| 久久99一本色道亚洲精品| 日本免费一级黄色录像| 91人妻人澡人人爽人人精品| 欧美日韩国产综合特黄| 日韩精品一区二区亚洲| 国产一区二区三区午夜精品| 黄色av尤物白丝在线播放网址| 久久福利视频视频一区二区| 亚洲日本中文字幕视频在线观看 | 久热99中文字幕视频在线| 黄片三级免费在线观看| 九九热视频免费在线视频| 欧美午夜色视频国产精品| 国产又粗又猛又黄又爽视频免费| 日韩一级欧美一级久久| 色鬼综合久久鬼色88| 亚洲品质一区二区三区| 高清一区二区三区大伊香蕉| 欧美日韩精品综合一区| 一二区中文字幕在线观看| 高清在线精品一区二区| 久久热在线视频免费观看| 亚洲伦片免费偷拍一区| 国产免费黄片一区二区| 激情内射日本一区二区三区| 少妇淫真视频一区二区| 自拍偷拍一区二区三区| 一二区不卡不卡在线观看| 国产精品午夜一区二区三区| 91欧美亚洲视频在线| 91精品视频免费播放| 懂色一区二区三区四区| 无套内射美女视频免费在线观看| 婷婷九月在线中文字幕| 精品欧美在线观看国产|