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

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

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

1 前言

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

2 簡單使用

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

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é)合,能夠使用鏈式編程來處理任務(wù)之間的邏輯關(guā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ù)的開啟一般有兩個方法,supplyAsync 和 runAsync,這兩個方法的別別在于:

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

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

3 異步處理

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

  • 1 Function , 既然是函數(shù),那么就會有一個入?yún)⒑头祷刂担梢杂糜谟嬎恪?/li>
  • 2 Comsumer , 是一個消費者,接收一個入?yún)⒌菦]有返回值,只用于消費。
  • 3 Supplier, 是一個提供者,不接受參數(shù),但是有一個返回值,可以用于對象的創(chuàng)建。
  • 4 Predicate, 用來做判斷使用,接收一個入?yún)?返回值是 布爾類型的,true 或者 false。

簡單的案例如下圖所示:

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

3.1 thenApply

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

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

3.2 thenAccept 和 thenRun

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

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

3.3 exceptionally 異常處理

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

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

3.4 whenComplete 方法完成之后

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

 // 返回結(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é)果,只不過 handle 有返回結(jié)果,接受的參數(shù)是一個 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";
 });

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

4 處理組合

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

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

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

下圖是方法的使用案例:

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

4.2 任一任務(wù)完成

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

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

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

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

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

thenCompose 的用法和 thenCombine 等的用法基本都是一樣的,只不過在返回參數(shù)上有所區(qū)別,結(jié)果是返回一個 Future, 入?yún)⑹且粋€ 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)分享過了兩個任務(wù)和一個任務(wù)的處理之后的操作,在本節(jié)中將分享 allOf 和 anyOf,這是多個任務(wù)的聚合處理,入?yún)⒍际嵌鄠€ CompletableFuture, 區(qū)別在于是任何一個任務(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java生成隨機數(shù)之Random與ThreadLocalRandom性能比較詳解

    Java生成隨機數(shù)之Random與ThreadLocalRandom性能比較詳解

    大家項目中如果有生成隨機數(shù)的需求,我想大多都會選擇使用Random來實現(xiàn),它內(nèi)部使用了CAS來實現(xiàn)。?實際上,JDK1.7之后,提供了另外一個生成隨機數(shù)的類ThreadLocalRandom,那么他們二者之間的性能是怎么樣的呢?本文就來詳細說說
    2022-12-12
  • Maven根據(jù)不同環(huán)境打包不同配置文件的方法

    Maven根據(jù)不同環(huán)境打包不同配置文件的方法

    這篇文章主要介紹了Maven根據(jù)不同環(huán)境打包不同配置文件的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • SpringBoot程序的打包與運行的實現(xiàn)

    SpringBoot程序的打包與運行的實現(xiàn)

    本文主要介紹了SpringBoot程序的打包與運行的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Monaco?Editor實現(xiàn)sql和java代碼提示實現(xiàn)示例

    Monaco?Editor實現(xiàn)sql和java代碼提示實現(xiàn)示例

    這篇文章主要為大家介紹了Monaco?Editor代碼提示sql和java實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • spring+springmvc+mybatis+maven入門實戰(zhàn)(超詳細教程)

    spring+springmvc+mybatis+maven入門實戰(zhàn)(超詳細教程)

    這篇文章主要介紹了spring+springmvc+mybatis+maven入門實戰(zhàn)(超詳細教程),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-05-05
  • 關(guān)于Java中如何實現(xiàn)文件的讀寫操作

    關(guān)于Java中如何實現(xiàn)文件的讀寫操作

    在Java中,可以使用File和FileInputStream、FileOutputStream、BufferedReader、PrintWriter等類來進行文件讀寫操作,需要的朋友可以參考下
    2023-05-05
  • java 算法之快速排序?qū)崿F(xiàn)代碼

    java 算法之快速排序?qū)崿F(xiàn)代碼

    這篇文章主要介紹了java 算法之快速排序?qū)崿F(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Mybatis入門教程之新增、更新、刪除功能

    Mybatis入門教程之新增、更新、刪除功能

    這篇文章給大家介紹了Mybatis進行基本的增刪改操作,非常不錯,具有參考借鑒價值,需要的的朋友參考下
    2017-02-02
  • Java圖形用戶界面設(shè)計(Swing)的介紹

    Java圖形用戶界面設(shè)計(Swing)的介紹

    看到多數(shù)人提到 Java 就以為是網(wǎng)絡(luò)開發(fā),其實不是這樣的,Java 也可以開發(fā)應(yīng)用程序,而且可以開發(fā)出漂亮的圖形用戶界面的應(yīng)用程序,因此,我寫下這篇文章,希望能帶你進入 Java 圖形用戶界面設(shè)計之門。
    2016-07-07
  • Java實現(xiàn)作業(yè)調(diào)度的示例代碼

    Java實現(xiàn)作業(yè)調(diào)度的示例代碼

    這篇文章主要為大家詳細介紹了如何利用Java實現(xiàn)SJF算法調(diào)度,要求測試數(shù)據(jù)可以隨即輸入或從文件中讀入,文中的示例代碼講解詳細,需要的可以參考一下
    2023-04-04

最新評論

临洮县| 宁南县| 桑植县| 林芝县| 枣强县| 保亭| 镇康县| 浦县| 阳春市| 开化县| 新昌县| 平湖市| 定襄县| 那曲县| 黄浦区| 堆龙德庆县| 明溪县| 密山市| 理塘县| 牡丹江市| 精河县| 东平县| 文水县| 苍梧县| 尚义县| 高安市| 宁陕县| 双鸭山市| 会东县| 娱乐| 炉霍县| 英吉沙县| 万宁市| 河北省| 清流县| 溆浦县| 随州市| 北辰区| 镶黄旗| 嘉善县| 永丰县|