亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java CompletableFuture使用方式

 更新時間:2024年07月04日 10:02:37   作者:xindoo  
這篇文章主要介紹了Java CompletableFuture使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

在我之前的文章IO密集型服務提升性能的三種方法中提到過,提升IO密集型應用性能有個方式就是異步編程,實現(xiàn)異步時一定會用到Future,使用多線程+Future我們可以讓多個任務同時去執(zhí)行,最后統(tǒng)一去獲取執(zhí)行結果,這樣整體執(zhí)行的時長就取決于最長的一個任務,比如如下代碼:

public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        System.out.println(new Date());
        Future<String> future1 = executorService.submit(() -> {
            Thread.sleep(5000);
            return new Date() + ":" + "thread1 result";
        });
        Future<String> future2 = executorService.submit(() -> {
            Thread.sleep(3000);
            return new Date() + ":" + "thread2 result";
        });
        try {
            System.out.println(future1.get());
            System.out.println(future2.get());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

上面代碼的運行時長是5s,如果兩個任務串行執(zhí)行的化,運行時間就會是8s,當多個任務多線程異步執(zhí)行時,最終總的執(zhí)行時長取決于最長任務的執(zhí)行時長。Future在大部分異步變成情況下,已經能很好的滿足我們異步變成的訴求了,但當我看到CompletableFuture這個東西的時候,才發(fā)現(xiàn)Future還是太簡單,我還是太年輕。

CompletableFuture除了和Future一樣可以獲取執(zhí)行結果外,它還**簡化了異常、提供了手動設置結果的接口、鏈式操作、結果組合、回調,**接下來我們通過一些代碼示例,來看下CompletableFuture這些特性如何吊打Future。

異常處理

在使用Future時,你只能在get()的時候抓取到異常,異常處理會和結果獲取的邏輯混在一起,有些時候處理起來會比較麻煩,而CompletableFuture提供了exceptionallyhandle 兩個api,可以很方便的添加異常處理邏輯,后續(xù)只需要直接使用get獲取結果即可,代碼示例如下:

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 故意拋出一個異常
            if (System.currentTimeMillis() % 2 == 0) {
                throw new RuntimeException("Exception occurred!");
            }
            return "Result";
        }, executorService);

        future = future.exceptionally(ex -> {
            // 對異常進行處理,并提供一個異常時的結果
            return "Default Value";
        });

        try {
            System.out.println(future.get()); // 輸出 "Default Value"
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

exceptionally api讓任務在運行過程中,如果抓到了Exception,就可以調用你給定的邏輯來處理異常。

與exceptionally就是handle方法,達到的效果一致,但使用略有不同,可以看出handle這個api是在任務執(zhí)行完成后,講exception和執(zhí)行結果共同處理一次。

        future = future.handle((result, ex) -> {
            if (ex != null) {
                return "Default Value";
            }
            return result;
        });
        try {
            System.out.println(future.get()); // 輸出 "Default Value"
        } catch (Exception e) {
            e.printStackTrace();
        }

手動設置結果

Future中,我們無法手動地完成一個任務或者設置任務的結果,這個任務的執(zhí)行結果完全取決于任務的執(zhí)行情況。

但在CompletableFuture,我們可以在任何時間點上手動設置結果或者標記任務為已完成。

舉個例子,我要通過接口獲取某個數(shù)據,但很要求時效性,如果超過1s我就不要接口調用結果了,而是返回一個默認值。

Future設置等待時間也可以實現(xiàn)類似的功能,但不是很直觀, CompletableFuture就很簡單直觀了。

public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                // 隨機sleep 0-2s
                Thread.sleep(ThreadLocalRandom.current().nextInt(2000));
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return "Result";
        }, executorService);
        CompletableFuture<String> finalFuture = future;
        // 1s后手動完成
        executorService.submit(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 手動地完成這個 CompletableFuture,并設置計算結果
            finalFuture.complete("Default Value");
        });

        try {
            System.out.println(future.get()); // 概率性輸出 "Default Value"
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

鏈式操作

鏈式操作意味著你可以將一個CompletableFuture的結果直接傳遞給另一個異步操作,而無需等待第一個操作完成。

這使得你可以更容易地編寫復雜的并發(fā)邏輯,這種非常適合需要將多個接口結果串起來的流程,有點像langChain,我們直接看示例代碼:

public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 第一個異步任務
            return "Hello";
        }).thenApplyAsync(result -> {
            // 第二個異步任務,依賴第一個任務的結果
            return result + " World";
        }).thenApplyAsync(result -> {
            // 第三個異步任務,依賴第二個任務的結果
            return result + "!";
        });
        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

這個示例比較簡單,在實際使用中,我們可以將三個任務替換成任何需要相互依賴的任務,你只需要定義每個任務的輸入和輸出,然后將它們連接在一起,就可以創(chuàng)建一個復雜的并發(fā)流程。

結果組合

CompletableFuture提供了幾個方法來組合或合并多個CompletableFuture的結果。

最常用的可能是thenCombineallOf方法。

以下是thenCombine方法的使用示例:

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    return "Hello";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    return "World!";
});

CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (s1, s2) -> {
    return s1 + ", " + s2;
});

try {
    String result = combinedFuture.get();
    System.out.println(result); // 輸出 "Hello, World!"
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

在上述代碼中,我們首先創(chuàng)建了兩個獨立的CompletableFuture,然后使用thenCombine方法將它們的結果組合在一起。

以下是allOf方法的使用示例:

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    return "Hello";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    return "World!";
});

CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);

// 當所有的 CompletableFuture 都完成時,獲取結果
allFutures.thenRun(() -> {
    try {
        String result1 = future1.get();
        String result2 = future2.get();
        System.out.println(result1 + ", " + result2); // 輸出 "Hello, World!"
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
});

可以看出thenCombine和allOf都實現(xiàn)了類似的功能,但兩者的側重點不同,thenCombine實現(xiàn)的是對執(zhí)行結果的聚合,而allOf實現(xiàn)的是對執(zhí)行完狀態(tài)的聚合,還是需要你去顯式調用get()方法去獲取結果的,所以你還是得根據具體需求來選擇使用thenCombine還是allOf。

回調

使用Future時,我們只能通過get()或者isDone()方法來獲取到任務是否執(zhí)行完成了,無法讓任務執(zhí)行完成后主動通知到我們,但CompletableFuture提供了一些回調方法,可以讓任務執(zhí)行完成后執(zhí)行結果處理的任務或者執(zhí)行一些通知的邏輯。

CompletableFuture提供了幾個方法來設置回調,如thenApply, thenAccept, 和 thenRun。

具體看代碼示例:

public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 異步任務
            return "Hello, World!";
        });

        future.thenApply(result -> {
            // 當 future 完成時,這個回調會被調用。
            // result 參數(shù)是 future 的結果。
            // 這個回調的結果會被包裝成一個新的 CompletableFuture。
            return result.length();
        }).thenAccept(length -> {
            // 當前面的 CompletableFuture 完成時,這個回調會被調用。
            // length 參數(shù)是前面 CompletableFuture 的結果。
            // 這個回調沒有返回值。
            System.out.println(length); // 輸出 "Hello, World!" 的長度
        }).thenRun(() -> {
            // 當前面的 CompletableFuture 完成時,這個回調會被調用。
            // 這個回調沒有輸入參數(shù),也沒有返回值。
            System.out.println("Done");
        });
    }

thenApply、thenAccept和thenRun都是在任務執(zhí)行完成后被調起,但他們定位有所不同,thenApply處理的結果可以被包裝成一個新的CompletableFuture,只后可以繼續(xù)鏈式調用。

但thenAccept只能接受輸入,無法提供輸出,所以他的定位是任務的收尾,比如可以將結果輸出。

而thenRun既沒有輸入也沒有輸出,所以它只是獲取到了任務執(zhí)行完的狀態(tài),任務的執(zhí)行結果是獲取不到的,所以它是最弱的。

總結

總結下本文,Future 盡管有用,但在功能上還是相對簡單。

CompletableFuture不僅提供了獲取執(zhí)行結果的能力,它還增添了異常處理、手動完成、鏈式操作、結果組合和回調等強大功能。

  • 異常處理: 利用exceptionallyhandle方法,可以簡化異常處理流程,使其更加直觀和易于管理。
  • 手動設置結果: CompletableFuture允許我們在任意時間點手動設置結果,增加了靈活性。
  • 鏈式操作: 通過鏈式操作,我們可以將不同的異步操作以流水線的方式串聯(lián)起來,編寫復雜的并發(fā)邏輯變得更加簡單。
  • 結果組合: thenCombineallOf方法能夠將多個CompletableFuture的結果合并,為我們提供了更多處理異步操作結果的方式。
  • 回調: 提供了thenApply, thenAccept, 和 thenRun等方法,允許我們在任務完成后進行結果處理或其他邏輯操作。

通過這些特性,CompletableFuture顯著地提升了異步編程的能力和靈活性。無論是簡化異常處理,還是實現(xiàn)復雜的異步邏輯,CompletableFuture都能夠幫助我們寫出更清晰、更高效的代碼。我相信通過本文的示例代碼,你可以更深入地理解CompletableFuture的強大之處,并在你的項目中充分利用它來提升性能。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • SpringBoot使用Shiro實現(xiàn)動態(tài)加載權限詳解流程

    SpringBoot使用Shiro實現(xiàn)動態(tài)加載權限詳解流程

    本文小編將基于?SpringBoot?集成?Shiro?實現(xiàn)動態(tài)uri權限,由前端vue在頁面配置uri,Java后端動態(tài)刷新權限,不用重啟項目,以及在頁面分配給用戶?角色?、?按鈕?、uri?權限后,后端動態(tài)分配權限,用戶無需在頁面重新登錄才能獲取最新權限,一切權限動態(tài)加載,靈活配置
    2022-07-07
  • Java前端Layer.open.btn驗證無效解決方法

    Java前端Layer.open.btn驗證無效解決方法

    在本篇文章里我們給大家整理了一篇關于Java前端Layer.open.btn驗證無效解決方法以及實例代碼,需要的朋友們可以參考學習下。
    2019-09-09
  • java監(jiān)聽器的實現(xiàn)和原理詳解

    java監(jiān)聽器的實現(xiàn)和原理詳解

    這篇文章主要給大家介紹了關于java監(jiān)聽器實現(xiàn)和原理的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-08-08
  • java 全角半角字符轉換的方法實例

    java 全角半角字符轉換的方法實例

    這篇文章主要介紹了java 全角半角字符轉換的方法,大家參考使用吧
    2013-11-11
  • 詳解SpringBoot+Dubbo集成ELK實戰(zhàn)

    詳解SpringBoot+Dubbo集成ELK實戰(zhàn)

    這篇文章主要介紹了詳解SpringBoot+Dubbo集成ELK實戰(zhàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-10-10
  • mybatis mapper互相引用resultMap啟動出錯的解決

    mybatis mapper互相引用resultMap啟動出錯的解決

    這篇文章主要介紹了mybatis mapper互相引用resultMap啟動出錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 輕松掌握java裝飾者模式

    輕松掌握java裝飾者模式

    這篇文章主要幫助大家輕松掌握java裝飾者模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Java集合ArrayList與LinkedList詳解

    Java集合ArrayList與LinkedList詳解

    這篇文章主要介紹了Java集合ArrayList與LinkedList詳解,對于ArrayList和LinkedList,他們都是List接口的一個實現(xiàn)類,并且我們知道他們的實現(xiàn)方式各不相同,例如ArrayList底層實現(xiàn)是一個數(shù)組
    2022-08-08
  • java阻塞隊列BlockingQueue詳細解讀

    java阻塞隊列BlockingQueue詳細解讀

    這篇文章主要介紹了java阻塞隊列BlockingQueue詳細解讀,在新增的Concurrent包中,BlockingQueue很好的解決了多線程中,如何高效安全“傳輸”數(shù)據的問題,通過這些高效并且線程安全的隊列類,為我們快速搭建高質量的多線程程序帶來極大的便利,需要的朋友可以參考下
    2023-10-10
  • Java設計模式之職責鏈模式詳解

    Java設計模式之職責鏈模式詳解

    Java設計模式中有很多種類別,例如單例模式、裝飾模式、觀察者模式等。本文將為大家詳細介紹其中的職責鏈模式,感興趣的可以了解一下
    2021-12-12

最新評論