Future和CompletableFuture的理解

爱为斯坦發表於2024-10-23

Future:

一個Future介面表示一個未來可能會返回的結果,它定義的方法有:

get():獲取結果(可能會等待)
get(long timeout, TimeUnit unit):獲取結果,但只等待指定的時間;
cancel(boolean mayInterruptIfRunning):取消當前任務;
isDone():判斷任務是否已完成。
在呼叫get()時,如果非同步任務已經完成,我們就直接獲得結果。如果非同步任務還沒有完成,那麼get()會阻塞,直到任務完成後才返回結果。
使用Future獲得非同步執行結果時,要麼呼叫阻塞方法get(),要麼輪詢看isDone()是否為true,這兩種方法都不是很好,因為主執行緒也會被迫等待。

CompletableFuture:

使用Future獲得非同步執行結果時,要麼呼叫阻塞方法get(),要麼輪詢看isDone()是否為true,這兩種方法都不是很好,因為主執行緒也會被迫等待。
從Java 8開始引入了CompletableFuture,它針對Future做了改進,可以傳入回撥物件,當非同步任務完成或者發生異常時,自動呼叫回撥物件的回撥方法
CompletableFuture的優點是:

  • 非同步任務結束時,會自動回撥某個物件的方法;
  • 非同步任務出錯時,會自動回撥某個物件的方法;
  • 主執行緒設定好回撥後,不再關心非同步任務的執行。

CompletableFuture可以指定非同步處理流程:

  • thenAccept()處理正常結果;
  • exceptional()處理異常結果;
  • thenApplyAsync()用於序列化另一個CompletableFuture
  • anyOf()allOf()用於並行化多個CompletableFuture

使用 CompletableFuture 的方法

  1. 直接使用 CompletableFuture 提交任務

    • 使用 CompletableFuture.runAsync()CompletableFuture.supplyAsync(),這些方法會使用預設執行緒池來執行非同步任務。
    • 適合快速啟動簡單的非同步操作,不需要額外的執行緒池管理。
  2. 使用 CompletableFuture 並指定執行緒池

    • 透過 supplyAsync()runAsync() 的過載版本,接受 Executor 引數,從而使用自定義執行緒池來執行任務。
    • 適合需要對執行緒池進行配置和管理的場景,如調整執行緒數量、佇列容量等。
    java複製程式碼ExecutorService executor = Executors.newFixedThreadPool(10);
    CompletableFuture.supplyAsync(() -> {
        // 執行某些操作
        return result;
    }, executor);
    
  3. 透過執行緒池中的 submit() 方法獲取 CompletableFuture

    • 使用 Executorsubmit() 方法(如 executor.submit()),結合 CompletableFuture 來獲取執行結果。
    • 這通常會返回 Future,但可以將結果轉換為 CompletableFuture 進行後續處理。
    java複製程式碼Future<String> future = executor.submit(() -> {
        // 執行某些操作
        return result;
    });
    CompletableFuture<String> completableFuture = CompletableFuture.completedFuture(future.get());
    

異常處理和結果回撥

  • 透過 thenApply()thenAccept()exceptionally() 等方法處理結果和異常。
  • CompletableFuture 提供了靈活的方式來組合多個非同步操作,使得非同步程式設計更容易。

參考:https://www.cnblogs.com/yaochunhui/p/15543298.html

相關文章