欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入學(xué)習(xí)java8?中的CompletableFuture

 更新時(shí)間:2022年05月05日 08:56:47   作者:斜月?  
本文主要介紹了java8中的CompletableFuture,CompletableFuture實(shí)現(xiàn)了CompletionStage接口和Future接口,前者是對(duì)后者的一個(gè)擴(kuò)展,增加了異步回調(diào)、流式處理、多個(gè)Future組合處理的能力,使Java在處理多任務(wù)的協(xié)同工作時(shí)更加順暢便利,下文需要的朋友可以參考一下

1 前言

在項(xiàng)目開(kāi)發(fā)中,異步化處理是非常常見(jiàn)的解決問(wèn)題的手段,異步化處理除了使用線程池之外,還可以使用 CompletableFuture 來(lái)實(shí)現(xiàn),在多任務(wù)處理且之間存在邏輯關(guān)系的情況下,就能夠體現(xiàn)出其巨大的優(yōu)勢(shì)和靈活性。CompletableFuture 底層使用的是 ForkJoinPool 線程池來(lái)實(shí)現(xiàn)線程的執(zhí)行和調(diào)度。

2 簡(jiǎn)單使用

在使用線程池時(shí),通常的使用方法如下所示:

ExecutorService service = Executors.newFixedThreadPool(3);
Callable<String> task1 = () ->{return "task1";};
Runnable task2 = () ->{
      System.out.println("task2 ");
};
// 用于提交任務(wù)根據(jù)是否獲取返回值分為 Callable 和 Runnable,分別使用 submit 和 execute 方法
service.submit(task1);
service.execute(task2);

但是在 CompletableFuture 中,使用方法還是有所區(qū)別的,是線程池和任務(wù)的結(jié)合,能夠使用鏈?zhǔn)骄幊虂?lái)處理任務(wù)之間的邏輯關(guān)系。

具體的使用如下所示:

// 使用默認(rèn)線程池
CompletableFuture<String> async1 = CompletableFuture.supplyAsync(() -> {
       log.info("async1 ... ");
       return "async1";
});
// 使用自定義線程池
CompletableFuture<String> async1 = CompletableFuture.supplyAsync(() -> {
       log.info("async1 ... ");
       return "async1";
}, Executors.newSingleThreadExecutor());
// runAsync 的使用方式
CompletableFuture<Void> future = CompletableFuture.runAsync(()-> {
            System.out.println("runAsync");
});

異步任務(wù)的開(kāi)啟一般有兩個(gè)方法,supplyAsync 和 runAsync,這兩個(gè)方法的別別在于:

  • 1 supplyAsync 不接受入?yún)?,但是?huì)有返回結(jié)果。
  • 2 runAsync 也是不接受入?yún)?,但是沒(méi)有返回結(jié)果。

這里需要先說(shuō)明一下,xxxAsync 的方法都是從使用線程池中獲取一個(gè)線程來(lái)處理任務(wù),不帶 Async 結(jié)尾的方法則是使用上一任務(wù)的線程繼續(xù)處理。

3 異步處理

在正式開(kāi)始之前,需要講解一下 java8 函數(shù)式編程的函數(shù),相信大家看到這么多的函數(shù)都會(huì)頭暈的,但是其中也是有規(guī)律可循的,先說(shuō)三個(gè)主要的:

  • 1 Function , 既然是函數(shù),那么就會(huì)有一個(gè)入?yún)⒑头祷刂?,可以用于?jì)算。
  • 2 Comsumer , 是一個(gè)消費(fèi)者,接收一個(gè)入?yún)⒌菦](méi)有返回值,只用于消費(fèi)。
  • 3 Supplier, 是一個(gè)提供者,不接受參數(shù),但是有一個(gè)返回值,可以用于對(duì)象的創(chuàng)建。
  • 4 Predicate, 用來(lái)做判斷使用,接收一個(gè)入?yún)?返回值是 布爾類型的,true 或者 false。

簡(jiǎn)單的案例如下圖所示:

有這基本的 4 個(gè),就可以進(jìn)行延伸了,比如 IntFunction 則是接收一個(gè) int 類型的參數(shù),處理完成后即可返回,前面的 Int 只是規(guī)定了入?yún)⒌念愋投?,再?BiConsumer , 則是接收兩個(gè)入?yún)?,Consumer 則是只能接收一個(gè)參數(shù)。依次類推就可以知道所有的函數(shù)式接口的功能,是不是很簡(jiǎn)單?

3.1 thenApply

thenApply 和 thenApplyAsync 都是接收一個(gè) Function 參數(shù),即接收一個(gè)參數(shù)并返回結(jié)果。區(qū)別在于前者是使用前一個(gè)任務(wù)的線程繼續(xù)處理,后者是從線程池中在獲取一個(gè)線程處理任務(wù)。

如上圖所示,thenApply 的任務(wù)處理和 future 使用的是一個(gè)線程,但是 thenApplyAsync 就換了一個(gè)線程繼續(xù)數(shù)據(jù)的處理。

3.2 thenAccept 和 thenRun

從方法名可以看到 thenAccept 和 thenRun 都是使用前一個(gè)人任務(wù)的線程進(jìn)行處理的。兩者都是在前一個(gè)任務(wù)完成后進(jìn)行處理,區(qū)別點(diǎn)在于 thenAccept 接收的是一個(gè) Consumer , 而 thenRun 接收的是一個(gè) Runnable, 因此兩者都沒(méi)有返回值,但是前者可以接收并消費(fèi)一個(gè)參數(shù),但是 thenRun 不能接收參數(shù)。這兩個(gè)方法的測(cè)試如下圖所示:

既然這兩個(gè)方法已經(jīng)搞清楚了,那么 thenAcceptAsync 和 thenRunAsync 是不是就順手學(xué)到了呢?異步編程的 API 真的是很簡(jiǎn)單。

3.3 exceptionally 異常處理

exceptionally 屬于異常處理流程,如果發(fā)生異常則需要進(jìn)行異常處理,需要將異常最為參數(shù)傳遞給 exceptionally, 而其需要的是一個(gè) Function 參數(shù),這里的異常處理也是同步進(jìn)行的,也是采用上一個(gè)任務(wù)的線程進(jìn)行處理。

// 拋出異常信息
CompletableFuture<String> exceptionally = future.exceptionally((ex) -> {
    log.info("error information " + ex.getLocalizedMessage());
    return ex.getMessage();
});

3.4 whenComplete 方法完成之后

這個(gè)方法是當(dāng)某個(gè)任務(wù)執(zhí)行完成之后進(jìn)行回調(diào),會(huì)將任務(wù)的執(zhí)行結(jié)果或者執(zhí)行期間的異常信息傳遞過(guò)來(lái)進(jìn)行處理,在正常的情況下,異常信息為 null,能夠得到任務(wù)的運(yùn)算結(jié)果,異常情況下,異常信息不為空,返回結(jié)果為 null。這里的 whenComplete 接受的是一個(gè) BiConsumer 函數(shù),也就是兩個(gè)入?yún)ⅲ瑳](méi)有返回結(jié)果,一個(gè)是方法的返回結(jié)果,一個(gè)則是任務(wù)處理過(guò)程中的異常信息。

 // 返回結(jié)果
 CompletableFuture<String> whenComplete = future.whenComplete((res, ex) -> {
     if (StrUtil.isNotBlank(res)) {
         log.info("task execute result {}", res);
     }
     if (res != null) {
         log.info("task error info {}", ex.getMessage());
     }
 });

知道了 whenComplete 方法,那么 whenCompleteAsync 方法的使用就知道了,就是異步處理了。

3.5 handle

handle 的使用和 whenComplete 方法類似,都是獲取任務(wù)的結(jié)果,只不過(guò) handle 有返回結(jié)果,接受的參數(shù)是一個(gè) BiFunction ,那么具體的使用方法如下圖所示:

 // handle 處理返回結(jié)果
 CompletableFuture<String> handle = future.handle((res, ex) -> {
     if (StrUtil.isNotBlank(res)) {
         log.info("task execute result {}", res);
         return "handle result exception";
     }
     if (res != null) {
         log.info("task error info {}", ex.getMessage());
     }
     return "handle result";
 });

通過(guò)以上的分析,我們已經(jīng)到得了以下規(guī)律:任何一個(gè)方法的實(shí)現(xiàn)都有三個(gè)類似的 API,一個(gè)是同步處理,一個(gè)是異步處理,一個(gè)是異步處理并指定線程池參數(shù)。目前已經(jīng)介紹了 6 個(gè) API,分別是 thenApplythenAccept,thenRunwhenCompletehandle 和 一個(gè)異常處理 exceptionally, 前五個(gè)舉一反三就知道了其他的兩個(gè)異步調(diào)用 API,掌握了其中的規(guī)律就不會(huì)覺(jué)得很多,無(wú)非就是同步異步,是否接收參數(shù)和有無(wú)返回值的區(qū)別。

4 處理組合

4.1 任務(wù)均完成后組合

thenCombine、thenAcceptBoth、runAfterBoth 這三個(gè)方法都是在兩個(gè) CompletableFuture 任務(wù)結(jié)束后在進(jìn)行執(zhí)行,區(qū)別在于是否接受參數(shù)以及是否有返回值,如圖所示查看其接受的參數(shù)。

  • thenCombine 方法為兩個(gè),第一個(gè)為 CompletionStage 對(duì)象即另一個(gè)異步任務(wù),第二個(gè)為 BiFunction ,接收兩個(gè)任務(wù)的處理結(jié)果并返回處理結(jié)果。
  • thenAcceptBoth 方法為兩個(gè),第一個(gè)為 CompletionStage 對(duì)象即另一個(gè)異步任務(wù),第二個(gè)為 BiConsumer, 接收兩個(gè)任務(wù)的處理結(jié)果不過(guò)沒(méi)有返回值。
  • runAfterBoth 方法為兩個(gè),第一個(gè)為 CompletionStage 對(duì)象即另一個(gè)異步任務(wù),第二個(gè)為 Runnable ,不接收兩個(gè)任務(wù)的處理結(jié)果,也沒(méi)有返回值。

下圖是方法的使用案例:

既然知道了這些方法的用法,那么 thenCombineAsync、thenAcceptBothAsyncrunAfterBothAsync 是不是就可以同理掌握了呢?

4.2 任一任務(wù)完成

前文提到的都是兩個(gè)任務(wù)均完成的情況,接下來(lái)的三個(gè)方法則是任何一個(gè)任務(wù)完成即可執(zhí)行下一個(gè)動(dòng)作,applyToEither、acceptEither、runAfterEither 這三個(gè)方法都是在兩個(gè)異步任務(wù)執(zhí)行結(jié)果之后的處理,任何一個(gè)任務(wù)執(zhí)行完畢之后就進(jìn)行繼續(xù)處理。

這里的任一任務(wù)執(zhí)行完成和兩者任務(wù)都執(zhí)行完在執(zhí)行是類似的,區(qū)別在于這里接收的是一個(gè)參數(shù):

  • 1 applyToEither 接收的參數(shù)是 CompletionStage 和 Function。
  • 2 acceptEither 接收的參數(shù)是 CompletionStage 和 Consumer。
  • 3 runAfterEither 接收的參數(shù)是 CompletionStage 和 Runnable。

這里已經(jīng)學(xué)習(xí)到了 applyToEitheracceptEither、runAfterEither 三個(gè)方法,那么類似的 applyToEitherAsyncacceptEitherAsync、runAfterEitherAsync 也可以知道其具體用法。

4.3 任務(wù)處理結(jié)果

thenCompose 的用法和 thenCombine 等的用法基本都是一樣的,只不過(guò)在返回參數(shù)上有所區(qū)別,結(jié)果是返回一個(gè) Future, 入?yún)⑹且粋€(gè) Function 。在了解了 thenCompose 之后,那么 thenComposeAsync 的使用方法就是類似了。

CompletableFuture<String> thenCompose = future.thenCompose((res) -> {
    log.info("result is {}", res);
    return CompletableFuture.supplyAsync(() -> {
        log.info("supplyAsync");
        return "result";
    });
});

4.4 所有或者任何

前面已經(jīng)分享過(guò)了兩個(gè)任務(wù)和一個(gè)任務(wù)的處理之后的操作,在本節(jié)中將分享 allOf 和 anyOf,這是多個(gè)任務(wù)的聚合處理,入?yún)⒍际嵌鄠€(gè) CompletableFuture, 區(qū)別在于是任何一個(gè)任務(wù)完成后就執(zhí)行后續(xù)任務(wù),還是所有的任務(wù)都完成后再繼續(xù)任務(wù)處理。

其使用方法如下所示:

CompletableFuture<Void> allOf = CompletableFuture.allOf(future);
CompletableFuture<Object> andOf = CompletableFuture.anyOf(future);

5 總結(jié)

文中,我們首先介紹了函數(shù)式編程的接口使用方法,然后分享了 CompletableFuture 的 API 使用方法。核心就是函數(shù)式編程接口,接收的是 Function、Consumer 還是 Runable , 其次就是否是 xxxAsync 異步處理。

到此這篇關(guān)于深入學(xué)習(xí)java8 中的CompletableFuture的文章就介紹到這了,更多相關(guān)java8 CompletableFuture 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java字符串抉擇

    java字符串抉擇

    下面給大家解析字符串連接方面的知識(shí),包括string,stringbuffer和stringbuilder等方面的知識(shí),對(duì)java字符串知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2016-12-12
  • Java設(shè)計(jì)模塊系列之書(shū)店管理系統(tǒng)單機(jī)版(一)

    Java設(shè)計(jì)模塊系列之書(shū)店管理系統(tǒng)單機(jī)版(一)

    這篇文章主要為大家詳細(xì)介紹了Java單機(jī)版的書(shū)店管理系統(tǒng)設(shè)計(jì)模塊和思想第一章,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Java Collections.sort()排序代碼案例

    Java Collections.sort()排序代碼案例

    這篇文章主要介紹了Java Collections.sort()排序代碼案例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • spring boot 配置Filter過(guò)濾器的方法

    spring boot 配置Filter過(guò)濾器的方法

    本篇文章主要介紹了spring boot 配置Filter過(guò)濾器的方法,實(shí)例分析了spring boot 配置Filter過(guò)濾器的技巧,有興趣的可以了解一下。
    2017-03-03
  • SpringBoot使用攔截器Interceptor實(shí)現(xiàn)統(tǒng)一角色權(quán)限校驗(yàn)

    SpringBoot使用攔截器Interceptor實(shí)現(xiàn)統(tǒng)一角色權(quán)限校驗(yàn)

    角色權(quán)限校驗(yàn),是保證接口安全必備的能力:有權(quán)限才可以操作,所以,一般對(duì)于這種通用邏輯,推薦不與主業(yè)務(wù)邏輯耦合,那么怎么來(lái)解耦,那么本文小編就給大家詳細(xì)講解如何使用攔截器Interceptor實(shí)現(xiàn)統(tǒng)一角色權(quán)限校驗(yàn),需要的朋友可以參考下
    2023-07-07
  • 在springboot中注入FilterRegistrationBean不生效的原因

    在springboot中注入FilterRegistrationBean不生效的原因

    這篇文章主要介紹了在springboot中注入FilterRegistrationBean不生效的原因及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java在運(yùn)行時(shí)能修改工作目錄嗎

    java在運(yùn)行時(shí)能修改工作目錄嗎

    這篇文章主要給大家介紹了關(guān)于java在運(yùn)行時(shí)能修改工作目錄的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Spring Boot jpa Service層代碼實(shí)例

    Spring Boot jpa Service層代碼實(shí)例

    這篇文章主要介紹了Spring Boot jpa Service層代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Java雜談之類和對(duì)象 封裝 構(gòu)造方法以及代碼塊詳解

    Java雜談之類和對(duì)象 封裝 構(gòu)造方法以及代碼塊詳解

    在現(xiàn)實(shí)世界中,真實(shí)存在的東西,比如吉普車(chē),卡丁車(chē),貨車(chē)。我們?cè)谡J(rèn)識(shí)它的時(shí)候就會(huì)在腦海中將它抽象為一種類別叫做車(chē)。 好了,那再計(jì)算機(jī)世界中,它同樣的也會(huì)這樣做
    2021-09-09
  • 非常全面的Java異常處理(全文干貨,值得收藏)

    非常全面的Java異常處理(全文干貨,值得收藏)

    這篇文章主要給大家介紹了非常全面的Java異常處理的相關(guān)資料,全文干貨,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11

最新評(píng)論