日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CompletableFuture API用法介绍(一)

發布時間:2025/1/21 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CompletableFuture API用法介绍(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 一、前言
    • 二、CompletableFuture
      • 1、主動完成計算
      • 2、創建異步任務
      • 3、計算完成時對結果的處理 whenComplete/exceptionally/handle
      • 4、結果轉換

一、前言

CompletableFuture類實現了CompletionStage和Future接口。Future是Java 5添加的類,用來描述一個異步計算的結果,但是獲取一個結果時方法較少,要么通過輪詢isDone,確認完成后,調用get()獲取值,要么調用get()設置一個超時時間。但是這個get()方法會阻塞著調用線程,這種阻塞的方式顯然和我們的異步編程的初衷相違背。
為了解決這個問題,JDK吸收了guava的設計思想,加入了Future的諸多擴展功能形成了CompletableFuture。

敲黑板:以Async結尾的方法都是可以異步執行的,如果指定了線程池,會在指定的線程池中執行,如果沒有指定,默認會在ForkJoinPool.commonPool()中執行

二、CompletableFuture

CompletableFuture 是Java 8 新增加的Api,該類實現,Future和CompletionStage兩個接口,提供了非常強大的Future的擴展功能,可以幫助我們簡化異步編程的復雜性,提供了函數式編程的能力,可以通過回調的方式處理計算結果,并且提供了轉換和組合CompletableFuture的方法

1、主動完成計算

  • public T get()
    該方法時阻塞方法,會等待計算結果完成
  • public T get(long timeout, TimeUnit unit)
    有時間限制的阻塞方法
  • public T getNow(T valueIfAbsent)
    立即獲取方法結果,如果沒有計算結束則返回傳的值
  • public T join()
    和 get() 方法類似也是主動阻塞線程,等待計算結果。和get() 方法有細微的差別

舉例如下:

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)

立即完成計算,并把結果設置為傳的值,返回是否設置成功

如果 CompletableFuture 沒有關聯任何的Callback、異步任務等,如果調用get方法,那會一直阻塞下去,可以使用complete方法主動完成計算。

2、創建異步任務

  • public static CompletableFuture completedFuture(U value)
    創建一個有初始值的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 結尾并且沒有 Executor 參數的,會默認使用 ForkJoinPool.commonPool() 作為它的線程池執行異步代碼。 以run開頭的,因為以 Runable 類型為參數所以沒有返回值。示例:

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、計算完成時對結果的處理 whenComplete/exceptionally/handle

當CompletableFuture的計算結果完成,或者拋出異常的時候,我們可以執行特定的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)
    參數類型為 BiConsumer<? super T, ? super Throwable> 會獲取上一步計算的計算結果和異常信息。以Async結尾的方法可能會使用其它的線程去執行,如果使用相同的線程池,也可能會被同一個線程選中執行,以下皆相同。
public static void completableFutureWhenComplete()throws Exception {CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return 20;}).whenCompleteAsync((v, e) -> {System.out.println(v);System.out.println(e);});System.out.println(future.get());}
  • public CompletableFuture exceptionally(Function<Throwable,? extends T> fn)
    該方法是對異常情況的處理,當函數異常時應該的返回值
public static void completableFutureExceptionally()throws Exception {CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return 10 / 0;}).whenCompleteAsync((v, e) -> {System.out.println(v);System.out.println(e);}).exceptionally((e) -> {System.out.println(e.getMessage());return 30;});System.out.println(future.get());}
  • 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 類型的參數,因此有 whenComplete 方法和 轉換的功能 (thenApply)
public static void completableFutureHand()throws Exception {CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 10 / 0).handle((t, e) -> {System.out.println(e.getMessage());return 10;});System.out.println(future.get());} }

4、結果轉換

CompletableFuture 由于有回調,可以不必等待一個計算完成而阻塞著調用線程,可以在一個結果計算完成之后緊接著執行某個Action。我們可以將這些操作串聯起來。

  • 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)
public static void completableFutureThenApply()throws Exception {CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 1).thenApply((a) -> {System.out.println(a);//1return a * 10;}).thenApply((a) -> {System.out.println(a);//10return a + 10;}).thenApply((a) -> {System.out.println(a);//20return a - 5;});System.out.println(future.get());//15} }

這些方法不是馬上執行的,也不會阻塞,而是前一個執行完成后繼續執行下一個。

和 handle 方法的區別是,handle 會處理正常計算值和異常,不會拋出異常。而 thenApply 只會處理正常計算值,有異常則拋出。

從上面API可以看出,我們的并發編程在jdk1.8變的更加簡單了。以上是部分CompletableFuture API用法。

總結

以上是生活随笔為你收集整理的CompletableFuture API用法介绍(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。