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

Java中CompletableFuture?的詳細(xì)介紹

 更新時間:2022年05月23日 09:08:23   作者:??旺財gg????  
這篇文章主要介紹了Java中的CompletableFuture,通過創(chuàng)建?CompletableFuture?的對象的工廠方法展開詳細(xì)的內(nèi)容介紹,需要的小伙伴可以參考一下

1.概述

1.0 創(chuàng)建 CompletableFuture 的對象的工廠方法

static?CompletableFuture<Void> runAsync(Runnable?runnable)
static?CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

runAsync 的參數(shù)是 Runnable, 返回值是 CompletableFuture, 意思是工廠方法創(chuàng)建的 CompletableFuture 對象封裝的任務(wù)沒有返回值。

例如:

CompletableFuture<Void> run = CompletableFuture.runAsync(()-> System.out.println("hello"));

而 suppyAsync 參數(shù)類型是 Supplier,返回值是CompletableFuture<U> , 意思是任務(wù)不接受參數(shù),但是會返回結(jié)果。

CompletableFuture<String> supply = CompletableFuture.supplyAsync(() -> {
    System.out.println("Hello");
    return "hello world!"";
});
System.out.println(supply.get());  //hello world!"

所以如果任務(wù)需要返回結(jié)果,那么應(yīng)該選擇 suppyAsync;否則可以選擇 runAsync。

1.1 non-async 和 async 區(qū)別

public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);

CompletableFuture 中有眾多類似這樣的方法,那么 non-async 和 async 和版本的方法究竟有什么區(qū)別呢? 參考官方文檔的描述:

Actions supplied for dependent completions of non-async methods may be performed by the thread that completes the current CompletableFuture, or by any other caller of a completion method.

翻譯:傳遞給 non-async 方法作為參數(shù)的函數(shù)(action)可能會在完成當(dāng)前的 CompletableFuture 的線程中執(zhí)行,也可能會在方法的調(diào)用者線程中執(zhí)行。

All async methods without an explicit Executor argument are performed using the ForkJoinPool.commonPool() (unless it does not support a parallelism level of at least two, in which case, a new Thread is created to run each task). To simplify monitoring, debugging, and tracking, all generated asynchronous tasks are instances of the marker interface CompletableFuture.AsynchronousCompletionTask.

翻譯:所有沒有Executor 參數(shù)的 async 方法都在 ForkJoinPool.commonPool()線程池中執(zhí)行(除非不支持最小并發(fā)度為2,這種情況下,每個任務(wù)會創(chuàng)建一個新線程去執(zhí)行)。為了簡化監(jiān)控、調(diào)試和追蹤,所有生成的異步任務(wù)都是接口 CompletableFuture.AsynchronousCompletionTask的實例。

從上面這兩段官方描述看。async 類方法比較容易理解,就是 CompletableFuture 實例的任務(wù)執(zhí)行完成后,會將 action 提交到缺省的異步線程池 ForkJoinPool.commonPool(),或者 async 類方法參數(shù)Executor executor 指定的線程池中執(zhí)行。

而對于 non-async 的描述則有點不明確。action 可能會在完成 CompletableFuture 實例任務(wù)的線程中執(zhí)行,也可能會在調(diào)用 thenRun(編排任務(wù)完成后執(zhí)行 action 的系列方法) 方法的線程中執(zhí)行。這個主要是看調(diào)用 thenRun 的時候,CompletableFuture 實例的任務(wù)是否已經(jīng)完成。如果沒有完成,那么action 會在完成任務(wù)的線程中執(zhí)行。如果任務(wù)已經(jīng)完成,則 action 會在調(diào)用thenAccept 等注冊方法的線程中執(zhí)行。

1.1.1 non-async 示例:注冊 action 的時候任務(wù)可能已經(jīng)結(jié)束

@Test
void testThenRunWithTaskCompleted() throws Exception{
    CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            System.out.println("[" + Thread.currentThread().getName() + "] " + " in task" );
            return 1;
        }
    }).thenRun(() -> {
        System.out.println("[" + Thread.currentThread().getName() + "] " + " in action" );
    });
    future.get();
}

運行結(jié)果:

[ForkJoinPool.commonPool-worker-1]  in task
[main]  in action

分析: 任務(wù)通過 CompletableFuture.supplyAsync 提交后,會以異步的方式在 ForkJoinPool.commonPool() 線程池中運行。這時候有兩個線程,一個是[ForkJoinPool.commonPool-worker-1] 執(zhí)行 Supplier.get 方法;一個是[main] 主線程提交完異步任務(wù)后,繼續(xù)調(diào)用 thenRun 編排任務(wù)完成后執(zhí)行 action。由于Supplier.get 非常簡單,幾乎立刻返回。所以很大概率在主線程調(diào)用 thenRun 編排任務(wù)完成后執(zhí)行 action的時候,異步任務(wù)已經(jīng)完成,所以 action 在主線程中執(zhí)行了。注:在筆者的電腦上幾乎100% 是這樣的調(diào)度方式。

1.1.2 non-async 示例:注冊 action 的時候任務(wù)未完成

@Test
void testThenRunWithTaskUncompleted() throws Exception{
    CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            System.out.println("[" + Thread.currentThread().getName() + "] " + " in task" );
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return new Random().nextInt(10);
        }
    }).thenRun(() -> {
        System.out.println("[" + Thread.currentThread().getName() + "] " + " in action" );
    });
    future.get();
}

運行結(jié)果:

[ForkJoinPool.commonPool-worker-1]  in task
[ForkJoinPool.commonPool-worker-1]  in action

分析:在 Supplier.get 加入 sleep,延遲任務(wù)結(jié)束。主線程提交完異步任務(wù)后,繼續(xù)調(diào)用 thenRun 編排任務(wù)完成后執(zhí)行 action 的時候,任務(wù)沒有結(jié)束。所以這個action 在完成任務(wù)的線程中執(zhí)行。

1.2 Run 類方法

Run 類方法指 thenRun、runAfterBoth、runAfterEither 等。Run 類方法的動作參數(shù)都是Runable action。例如 thenRun(Runnable action)。這就意味著這個 action 不關(guān)心任務(wù)的結(jié)果,action 本身也沒有返回值。只是為了實現(xiàn)在完成任務(wù)后執(zhí)行一個動作的目的。

1.3 Accept 類方法

Accept 類方法指 thenAccept、runAcceptBoth、runAcceptEither 等。Accept 類方法的動作參數(shù)都是Consumer<? super T> action。例如 thenAccept(Consumer<? super T> action)。如方法名和參數(shù)所示,action 是接受并消費任務(wù)結(jié)果的消費者,action 沒有返回值

1.4 Apply 類方法

Apply 類方法指 thenApply、applyToEither 等。Apply 類方法的動作參數(shù)都是Function<? super T,? extends U> fn。例如 thenApply(Function<? super T,? extends U> fn)。如方法名和參數(shù)所示,action 將任務(wù)結(jié)果應(yīng)用函數(shù)參數(shù) fn 做轉(zhuǎn)換,返回轉(zhuǎn)換后的結(jié)果,類似于 stream 中的 map。

2 單個任務(wù)執(zhí)行完成后執(zhí)行一個動作(action)

方法說明
public CompletableFuture<Void> thenRun(Runnable action)
thenRunAsync(Runnable action)
thenRunAsync(Runnable action, Executor executor)
任務(wù)完成后執(zhí)行 action,action 中不關(guān)心任務(wù)的結(jié)果,action 也沒有返回值
public CompletableFuture<Void> thenAccept(Consumer<? super T> action)
thenAcceptAsync(Consumer<? super T> action)
thenAcceptAsync(Consumer<? super T> action)
任務(wù)完成后執(zhí)行 action。如方法名和參數(shù)所示,action 是接受并消費任務(wù)結(jié)果的消費者,action 沒有返回值
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
thenApplyAsync(Function<? super T,? extends U> fn)
thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)
任務(wù)完成后執(zhí)行 action。action 將任務(wù)結(jié)果應(yīng)用 action 的函數(shù)參數(shù)做轉(zhuǎn)換,返回轉(zhuǎn)換后的結(jié)果,類似于 stream 中的 map
public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action)
whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action)
whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor)
任務(wù)完成后或者異常時運行action。action 是接受并消費任務(wù)結(jié)果的消費者,并且有返回值??梢哉J(rèn)為是支持異常處理的 thenAccept 版本。
public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn)
handleAsync(BiFunction<? super T, Throwable, ? extends U> fn)
handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor)
任務(wù)完成后或者異常時運行action。可以認(rèn)為是支持異常處理的 thenApply 版本。
public CompletableFuture exceptionally(Function<Throwable, ? extends T> fn)如果任務(wù)或者 action 發(fā)生異常,則會觸發(fā)exceptionally的調(diào)用相當(dāng)于 try...catch

2.0 示例 exceptionally

@Test
void testCompletableFutureExceptionally(){
    CompletableFuture<Integer> first = CompletableFuture
            .supplyAsync(() -> {
                if (true) {
                    throw new RuntimeException("exception in task");
                }
                return "hello world";
            })
            .thenApply(data -> {
                if (true) {
                    throw new RuntimeException("exception in action");
                }
                return 1;
            })
            .exceptionally(e -> {
                System.out.println("[" + Thread.currentThread().getName() + "] " + " print exception stack trace" );
                e.printStackTrace(); // 異常捕捉處理,前面兩個處理環(huán)節(jié)的日常都能捕獲
                return 0;
            });
}

3 兩個任務(wù)執(zhí)行編排

下面表格列出的每個方法都有對應(yīng)兩個版本的 async 方法,一個有executor 參數(shù),一個沒有。為了表格盡量簡潔,表格中就不再列出async 方法了

方法說明
public <U> CompletableFuture<U> thenCompose(Function<? super T,? extends CompletionStage> fn)串行組合兩個 CompletableFuture 任務(wù),后一個任務(wù)依賴前一個任務(wù)的結(jié)果,后一個任務(wù)可以返回與第一個任務(wù)不同類型的返回值。執(zhí)行后一個任務(wù)的線程與前面討論 action 執(zhí)行的線程類似。
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other, Runnable action)這里有兩個并行任務(wù),一個是runAfterBoth 調(diào)用本身所屬的CompletableFuture 實例A,一個是參數(shù) other 引用的任務(wù)B。兩個并行任務(wù)都完成后執(zhí)行 action,action 中不關(guān)心任務(wù)的結(jié)果,action 也沒有返回值
public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action)與runAfterBoth 類似,也有兩個并行任務(wù) A 和 B。兩個并行任務(wù)都完成后執(zhí)行 action。如方法名和參數(shù)所示,action 是接受并消費兩個任務(wù)結(jié)果的消費者,action 沒有返回值
public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)與runAfterBoth 類似,也有兩個并行任務(wù) A 和 B。兩個并行任務(wù)都完成后執(zhí)行 action,action 依賴兩個任務(wù)的結(jié)果,并對結(jié)果做轉(zhuǎn)換,返回一個新值
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other, Runnable action)與runAfterBoth 類似,也有兩個并行任務(wù) A 和 B。兩個并行任務(wù)任意一個完成后執(zhí)行 action,action 中不關(guān)心任務(wù)的結(jié)果,action 也沒有返回值
public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)與runAfterBoth 類似,也有兩個并行任務(wù) A 和 B。兩個并行任務(wù)任意一個完成后執(zhí)行 action。如方法名和參數(shù)所示,action 是接受并消費兩個任務(wù)結(jié)果的消費者,action 沒有返回值
public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn)與runAfterBoth 類似,也有兩個并行任務(wù) A 和 B。兩個并行任務(wù)任意一個完成后執(zhí)行 action。action 將任務(wù)結(jié)果應(yīng)用 action 的函數(shù)參數(shù)做轉(zhuǎn)換,返回轉(zhuǎn)換后的結(jié)果,類似于 stream 中的 map

4 多個任務(wù)執(zhí)行編排

下面表格列出的每個方法都有對應(yīng)兩個版本的 async 方法,一個有executor 參數(shù),一個沒有。為了表格盡量簡潔,表格中就不再列出async 方法了

方法說明
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)所有參數(shù)引用的任務(wù)都完成后,才觸發(fā)執(zhí)行當(dāng)前的 CompletableFuture 實例任務(wù)。
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)參數(shù)引用的任務(wù)中任何一個完成后,就會觸發(fā)執(zhí)行當(dāng)前的 CompletableFuture 實例任務(wù)。

5 CompletableFuture 其他方法

方法說明
public boolean cancel(boolean mayInterruptIfRunning)如果任務(wù)未完成,以 CancellationException 異常結(jié)束任務(wù)。
public boolean isCancelled()判斷任務(wù)是否取消。
public T join()阻塞等待 獲取返回值
public T get() throws InterruptedException, ExecutionException
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
阻塞等待(有超時重載版本)獲取返回值。get 與 join區(qū)別,get 會拋出 checked 異常,調(diào)用代碼需要處理異常。join 沒有超時重載版本。
public T getNow(T valueIfAbsent)獲取返回值,如果任務(wù)未完成則返回valueIfAbsent 參數(shù)指定value
public boolean isDone()任務(wù)是否執(zhí)行完成

到此這篇關(guān)于Java中CompletableFuture 的詳細(xì)介紹的文章就介紹到這了,更多相關(guān)CompletableFuture 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中CountDownLatch工具類詳細(xì)解析

    Java中CountDownLatch工具類詳細(xì)解析

    這篇文章主要介紹了Java中CountDownLatch工具類詳細(xì)解析,創(chuàng)建CountDownLatch對象時,會傳入一個count數(shù)值,該對象每次調(diào)用countDown()方法會使count?--?,就是count每次減1,需要的朋友可以參考下
    2023-11-11
  • 8個Spring事務(wù)失效場景詳解

    8個Spring事務(wù)失效場景詳解

    相信大家對Spring種事務(wù)的使用并不陌生,但是你可能只是停留在基礎(chǔ)的使用層面上。今天,我們就簡單來說下Spring事務(wù)的原理,然后總結(jié)一下spring事務(wù)失敗的場景,并提出對應(yīng)的解決方案,需要的可以參考一下
    2022-12-12
  • 如何實現(xiàn)自定義SpringBoot的Starter組件

    如何實現(xiàn)自定義SpringBoot的Starter組件

    這篇文章主要介紹了實現(xiàn)自定義SpringBoot的Starter組件的示例代碼,想要自定義starter組件,首先要了解springboot是如何加載starter的,也就是springboot的自動裝配機制原理,本文結(jié)合示例代碼詳細(xì)講解,需要的朋友可以參考下
    2023-02-02
  • SpringCloud?Feign?傳輸Date類型參數(shù)存在誤差的問題

    SpringCloud?Feign?傳輸Date類型參數(shù)存在誤差的問題

    這篇文章主要介紹了SpringCloud?Feign?傳輸Date類型參數(shù)存在誤差的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Spring通過三級緩存解決循環(huán)依賴問題的過程詳解

    Spring通過三級緩存解決循環(huán)依賴問題的過程詳解

    循環(huán)依賴指的是在對象之間存在相互依賴關(guān)系,形成一個閉環(huán),導(dǎo)致無法準(zhǔn)確地完成對象的創(chuàng)建和初始化,本文主要介紹了Spring通過三級緩存解決循環(huán)依賴的方法,需要的可以參考下
    2023-10-10
  • JAVA多線程之實現(xiàn)用戶任務(wù)排隊并預(yù)估排隊時長

    JAVA多線程之實現(xiàn)用戶任務(wù)排隊并預(yù)估排隊時長

    本文主要介紹了Java多線程之實現(xiàn)用戶任務(wù)排隊并預(yù)估排隊時長的問題,文中的代碼具有一定的學(xué)習(xí)和工作價值,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)一下吧
    2021-12-12
  • JMeter導(dǎo)入自定義的Jar包的詳解教程

    JMeter導(dǎo)入自定義的Jar包的詳解教程

    這篇文章主要介紹了JMeter導(dǎo)入自定義的Jar包的詳解教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • Springboot之@Async不執(zhí)行原因及分析

    Springboot之@Async不執(zhí)行原因及分析

    這篇文章主要介紹了Springboot之@Async不執(zhí)行原因及分析,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 淺談Java8 的foreach跳出循環(huán)break/return

    淺談Java8 的foreach跳出循環(huán)break/return

    這篇文章主要介紹了Java8 的foreach跳出循環(huán)break/return,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java圖形界面GUI布局方式(小結(jié))

    Java圖形界面GUI布局方式(小結(jié))

    這篇文章主要介紹了Java圖形界面GUI布局方式(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04

最新評論