簡體   English   中英

CompletableFuture、Future 和 RxJava 的 Observable 的區別

[英]Difference between CompletableFuture, Future and RxJava's Observable

我想知道CompletableFutureFutureObservable RxJava之間的區別。

我所知道的是都是異步的但是

Future.get()阻塞線程

CompletableFuture提供回調方法

RxJava Observable --- 類似於CompletableFuture並具有其他好處(不確定)

例如:如果客戶端需要進行多個服務調用,而當我們使用Futures (Java) Future.get()將按順序執行...想知道它在 RxJava 中如何更好..

和文檔http://reactivex.io/intro.html

使用 Futures 來優化組合條件異步執行流是很困難的(或者不可能,因為每個請求的延遲在運行時會有所不同)。 這當然可以完成,但它很快變得復雜(因此容易出錯)或者它過早地阻塞 Future.get(),這消除了異步執行的好處。

真的很想知道RxJava如何解決這個問題。 我發現從文檔中很難理解。

期貨

Futures是在 Java 5 (2004) 中引入的。 它們基本上是尚未完成的操作結果的占位符。 操作完成后, Future將包含該結果。 例如,操作可以是提交給ExecutorServiceRunnableCallable實例。 操作的提交者可以使用Future對象來檢查操作是否isDone() ,或者使用阻塞的get()方法等待它完成。

例子:

/**
* A task that sleeps for a second, then returns 1
**/
public static class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        Thread.sleep(1000);
        return 1;
    }

}

public static void main(String[] args) throws Exception{
    ExecutorService exec = Executors.newSingleThreadExecutor();
    Future<Integer> f = exec.submit(new MyCallable());

    System.out.println(f.isDone()); //False

    System.out.println(f.get()); //Waits until the task is done, then prints 1
}

可完成期貨

CompletableFutures是在 Java 8 (2014) 中引入的。 它們實際上是常規 Futures 的演變,受到谷歌的Listenable Futures 的啟發,這是Guava庫的一部分。 它們是 Futures,還允許您將任務串成一個鏈。 你可以使用它們告訴某個工作線程“去做一些任務 X,當你完成后,使用 X 的結果去做另一件事”。 使用 CompletableFutures,您可以對操作的結果執行某些操作,而無需實際阻塞線程以等待結果。 這是一個簡單的例子:

/**
* A supplier that sleeps for a second, and then returns one
**/
public static class MySupplier implements Supplier<Integer> {

    @Override
    public Integer get() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            //Do nothing
        }
        return 1;
    }
}

/**
* A (pure) function that adds one to a given Integer
**/
public static class PlusOne implements Function<Integer, Integer> {

    @Override
    public Integer apply(Integer x) {
        return x + 1;
    }
}

public static void main(String[] args) throws Exception {
    ExecutorService exec = Executors.newSingleThreadExecutor();
    CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new MySupplier(), exec);
    System.out.println(f.isDone()); // False
    CompletableFuture<Integer> f2 = f.thenApply(new PlusOne());
    System.out.println(f2.get()); // Waits until the "calculation" is done, then prints 2
}

RxJava

RxJava是 Netflix 創建的用於響應式編程的完整庫。 乍一看,它看起來類似於Java 8 的流 它是,除了它更強大。

與 Futures 類似,RxJava 可用於將一堆同步或異步操作串在一起以創建處理管道。 與一次性使用的 Futures 不同,RxJava 可以處理零個或多個項目的 包括具有無限數量項目的永無止境的流。 由於一組令人難以置信的豐富的運算符,它也更加靈活和強大。

與 Java 8 的流不同,RxJava 還具有 背壓機制,允許它處理處理管道的不同部分在不同線程中以不同速率運行的情況

RxJava 的缺點是,盡管有可靠的文檔,但由於所涉及的范式轉換,它是一個具有挑戰性的庫。 Rx 代碼也可能是調試的噩夢,尤其是在涉及多個線程的情況下,更糟糕的是 - 如果需要背壓。

如果你想深入了解,官網上有一整各種教程,還有官方文檔Javadoc 您還可以查看一些視頻,例如這個視頻,它簡要介紹了 Rx,並討論了 Rx 和 Futures 之間的區別。

獎勵:Java 9 反應式流

Java 9 的 Reactive Streams aka Flow API是一組由各種反應流庫(例如RxJava 2Akka StreamsVertx )實現的接口 它們允許這些反應式庫相互連接,同時保留所有重要的背壓。

我從 0.9 開始使用 Rx Java,現在是 1.3.2 並且很快遷移到 2.x 我在一個我已經工作了 8 年的私人項目中使用它。

如果沒有這個庫,我就不會再編程了。 一開始我持懷疑態度,但這是你需要創造的一種完全不同的心態。 剛開始時安靜困難。 我有時會盯着彈珠看好幾個小時……哈哈

這只是一個練習和真正了解流程的問題(又名可觀察者和觀察者的契約),一旦你到達那里,你就會討厭這樣做。

對我來說,那個庫並沒有真正的缺點。

用例:我有一個包含 9 個儀表(CPU、內存、網絡等...)的監視器視圖。 啟動視圖時,視圖將自己訂閱到一個系統監視器類,該類返回一個包含 9 米的所有數據的可觀察值(間隔)。 它將每秒向視圖推送一個新結果(因此不輪詢!!!)。 該 observable 使用平面圖同時(異步!)從 9 個不同來源獲取數據,並將結果壓縮到一個新模型中,您的視圖將在 onNext() 上獲得。

你怎么會用期貨、可完成品等來做這件事……祝你好運! :)

Rx Java 為我解決了許多編程問題,並在某種程度上讓我變得更容易……

好處:

  • 無國界!!! (重要的事情要提,最重要的也許是)
  • 開箱即用的線程管理
  • 構建具有自己生命周期的序列
  • 一切都是可觀察的,所以鏈接很容易
  • 編寫更少的代碼
  • 類路徑上的單個 jar(非常輕量級)
  • 高並發
  • 不再有回調地獄
  • 基於訂閱者(消費者和生產者之間的緊密契約)
  • 背壓策略(斷路器之類)
  • 出色的錯誤處理和恢復
  • 非常好的文檔(大理石 <3)
  • 完全控制
  • 還有很多 ...

缺點: - 難以測試

CompletableFuture 相對於普通 Future 的主要優勢在於 CompletableFuture 利用極其強大的流 API 並為您提供回調處理程序來鏈接您的任務,如果您使用普通 Future,則絕對不存在。 除了提供異步架構外,CompletableFuture 是處理計算繁重的 map-reduce 任務的方法,而不必擔心應用程序性能。

所有三個接口都用於將值從生產者傳輸到消費者。 消費者可以有兩種:

  • 同步:消費者進行阻塞調用,當值准備好時返回
  • 異步:當值准備好時,調用消費者的回調方法

此外,通信接口在其他方面有所不同:

  • 能夠傳輸多個值中的單個值
  • 如果有多個值,可以支持或不支持背壓

其結果:

  • Future使用同步接口傳輸單個值

  • CompletableFuture使用同步和異步接口傳輸單個值

  • Rx使用帶有背壓的異步接口傳輸多個值

此外,所有這些通信設施都支持傳輸異常。 這並非總是如此。 例如, BlockingQueue沒有。

Java 的Future是一個占位符,用於保存將來會通過阻塞 API 完成的內容。 您必須使用它的' isDone()方法定期輪詢它以檢查該任務是否已完成。 當然,您可以實現自己的異步代碼來管理輪詢邏輯。 但是,它會產生更多樣板代碼和調試開銷。

Java 的CompletableFuture是由 Scala 的 Future 創新的。 它帶有一個內部回調方法。 一旦完成,將觸發回調方法並告訴線程應該執行下游操作。 這就是為什么它有thenApply方法來對包裹在CompletableFuture的對象做進一步的操作。

RxJava 的ObservableCompletableFuture的增強版本。 它允許您處理背壓。 在我們上面提到的thenApply方法(甚至它的兄弟thenApplyAsync )中,可能會發生這種情況:下游方法想要調用有時可能變得不可用的外部服務。 在這種情況下, CompleteableFuture將完全失敗,您必須自己處理錯誤。 但是, Observable允許您處理背壓並在外部服務可用后繼續執行。

此外,還有一個類似Observable接口: Flowable 它們是為不同的目的而設計的。 通常Flowable專用於處理冷和非定時操作,而Observable專用於處理需要即時響應的執行。 在這里查看官方文檔: https : //github.com/ReactiveX/RxJava#backpressure

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM