CompletableFuture API用法介绍(一)
文章目錄
- 一、前言
- 二、CompletableFuture
- 1、主動完成計算
- 2、創(chuàng)建異步任務(wù)
- 3、計算完成時對結(jié)果的處理 whenComplete/exceptionally/handle
- 4、結(jié)果轉(zhuǎn)換
一、前言
CompletableFuture類實現(xiàn)了CompletionStage和Future接口。Future是Java 5添加的類,用來描述一個異步計算的結(jié)果,但是獲取一個結(jié)果時方法較少,要么通過輪詢isDone,確認(rèn)完成后,調(diào)用get()獲取值,要么調(diào)用get()設(shè)置一個超時時間。但是這個get()方法會阻塞著調(diào)用線程,這種阻塞的方式顯然和我們的異步編程的初衷相違背。
為了解決這個問題,JDK吸收了guava的設(shè)計思想,加入了Future的諸多擴(kuò)展功能形成了CompletableFuture。
敲黑板:以Async結(jié)尾的方法都是可以異步執(zhí)行的,如果指定了線程池,會在指定的線程池中執(zhí)行,如果沒有指定,默認(rèn)會在ForkJoinPool.commonPool()中執(zhí)行
二、CompletableFuture
CompletableFuture 是Java 8 新增加的Api,該類實現(xiàn),Future和CompletionStage兩個接口,提供了非常強(qiáng)大的Future的擴(kuò)展功能,可以幫助我們簡化異步編程的復(fù)雜性,提供了函數(shù)式編程的能力,可以通過回調(diào)的方式處理計算結(jié)果,并且提供了轉(zhuǎn)換和組合CompletableFuture的方法
1、主動完成計算
- public T get()
該方法時阻塞方法,會等待計算結(jié)果完成 - public T get(long timeout, TimeUnit unit)
有時間限制的阻塞方法 - public T getNow(T valueIfAbsent)
立即獲取方法結(jié)果,如果沒有計算結(jié)束則返回傳的值 - public T join()
和 get() 方法類似也是主動阻塞線程,等待計算結(jié)果。和get() 方法有細(xì)微的差別
舉例如下:
public static void completableFutureGet() throws Exception{CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return 100 * 10;});System.out.println(completableFuture.get());System.out.println(completableFuture.get(1000, TimeUnit.MICROSECONDS));System.out.println(completableFuture.join());System.out.println(completableFuture.getNow(1));}- public boolean complete(T value)
立即完成計算,并把結(jié)果設(shè)置為傳的值,返回是否設(shè)置成功
如果 CompletableFuture 沒有關(guān)聯(lián)任何的Callback、異步任務(wù)等,如果調(diào)用get方法,那會一直阻塞下去,可以使用complete方法主動完成計算。
2、創(chuàng)建異步任務(wù)
- public static CompletableFuture completedFuture(U value)
創(chuàng)建一個有初始值的CompletableFuture - public static CompletableFuture runAsync(Runnable runnable)
- public static CompletableFuture runAsync(Runnable runnable, Executor executor)
- public static CompletableFuture supplyAsync(Supplier supplier)
- public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)
以上四個方法中,以 Async 結(jié)尾并且沒有 Executor 參數(shù)的,會默認(rèn)使用 ForkJoinPool.commonPool() 作為它的線程池執(zhí)行異步代碼。 以run開頭的,因為以 Runable 類型為參數(shù)所以沒有返回值。示例:
public static void completableFutureSupplyAsync()throws Exception {CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> System.out.println("runAsync"));CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "supplyAsync");System.out.println(future1.get());System.out.println(future2.get());}3、計算完成時對結(jié)果的處理 whenComplete/exceptionally/handle
當(dāng)CompletableFuture的計算結(jié)果完成,或者拋出異常的時候,我們可以執(zhí)行特定的Action。主要是下面的方法:
- public CompletableFuture whenComplete(BiConsumer<? super T,? super Throwable> action)
- public CompletableFuture whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
- public CompletableFuture whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
參數(shù)類型為 BiConsumer<? super T, ? super Throwable> 會獲取上一步計算的計算結(jié)果和異常信息。以Async結(jié)尾的方法可能會使用其它的線程去執(zhí)行,如果使用相同的線程池,也可能會被同一個線程選中執(zhí)行,以下皆相同。
- public CompletableFuture exceptionally(Function<Throwable,? extends T> fn)
該方法是對異常情況的處理,當(dāng)函數(shù)異常時應(yīng)該的返回值
- public CompletableFuture handle(BiFunction<? super T,Throwable,? extends U> fn)
- public CompletableFuture handleAsync(BiFunction<? super T,Throwable,? extends U> fn)
- public CompletableFuture handleAsync(BiFunction<? super T,Throwable,? extends U> fn, Executor executor)
handle 方法和whenComplete方法類似,只不過接收的是一個 BiFunction<? super T,Throwable,? extends U> fn 類型的參數(shù),因此有 whenComplete 方法和 轉(zhuǎn)換的功能 (thenApply)
4、結(jié)果轉(zhuǎn)換
CompletableFuture 由于有回調(diào),可以不必等待一個計算完成而阻塞著調(diào)用線程,可以在一個結(jié)果計算完成之后緊接著執(zhí)行某個Action。我們可以將這些操作串聯(lián)起來。
- public CompletableFuture thenApply(Function<? super T,? extends U> fn)
- public CompletableFuture thenApplyAsync(Function<? super T,? extends U> fn)
- public CompletableFuture thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)
這些方法不是馬上執(zhí)行的,也不會阻塞,而是前一個執(zhí)行完成后繼續(xù)執(zhí)行下一個。
和 handle 方法的區(qū)別是,handle 會處理正常計算值和異常,不會拋出異常。而 thenApply 只會處理正常計算值,有異常則拋出。
從上面API可以看出,我們的并發(fā)編程在jdk1.8變的更加簡單了。以上是部分CompletableFuture API用法。
總結(jié)
以上是生活随笔為你收集整理的CompletableFuture API用法介绍(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JWT(JSON Web Token)简
- 下一篇: CompletableFuture AP