web-dev-qa-db-ja.com

CompletableFuture、FutureとRxJavaのオブザーバブルの違い

CompletableFutureFuture、およびObservableRxJavaの違いを知りたいのですが。

私が知っているのはすべて非同期だが

Future.get()はスレッドをブロックします

CompletableFutureはコールバックメソッドを与えます

RxJava Observable --- CompletableFutureと似ていますが、その他の利点があります(確実ではありません)。

たとえば、クライアントが複数のサービス呼び出しを行う必要があり、Futures(Java)を使用する場合はFuture.get()が順次実行されます。

そしてドキュメンテーション http://reactivex.io/intro.html は言う

Futuresを使用して条件付き非同期実行フローを最適に構成することは困難です(または各要求の待ち時間が実行時に異なるため不可能です)。もちろんこれは可能ですが、すぐに複雑になり(したがってエラーが発生しやすく)、またはFuture.get()で時期尚早にブロックされ、非同期実行の利点がなくなります

RxJavaがこの問題をどのように解決するかを知りたいと本当に興味があります。文書から理解するのは難しいと思いました。

150
shiv455

先物

Futures はJava 5(2004)で導入されました。彼らは基本的にまだ起こっていない結果のプレースホルダーです。彼らはその操作が完了したら、ある操作の結果を保持することを約束します。この操作は、 Runnable または Callable インスタンスに送信され、 ExecutorService に送信されます。操作の実行依頼者は、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

CompletableFutures はJava 8(2014)で導入されました。それらは実際にはGoogleの Listenable FuturesGuava ライブラリーの一部に触発された通常の先物の進化です。彼らはまた、あなたがチェーンで一緒にタスクをつなぐことを可能にする先物です。それらを使用して、ワーカースレッドに「タスクXを実行し、完了したら、Xの結果を使用してこれ以外のことを実行する」ように指示できます。これは簡単な例です:

/**
* 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を使用して、一連の同期または非同期アクションをまとめて処理パイプラインを作成できます。使い捨ての先物とは異なり、RxJavaは0個以上のアイテムのストリームで動作します。無限の数のアイテムを持つ終わりのないストリームを含みます。信じられないほど豊富な 演算子のセット のおかげで、はるかに柔軟で強力です。

Java 8のストリームとは異なり、RxJavaには バックプレッシャ メカニズムもあります。これにより、処理パイプラインの異なる部分が異なるスレッドで動作する場合を異なるレートで処理できます。 ).

RxJavaの欠点は、しっかりしたドキュメントにもかかわらず、パラダイムシフトがあるために学ぶのが難しいライブラリだということです。 Rxコードは、特に複数のスレッドが関与している場合、そしてさらに悪いことに - バックプレッシャーが必要な場合には、デバッグするのに悪夢となる可能性もあります。

あなたがそれに参加したいのであれば、公式のWebサイト上のさまざまなチュートリアルの全体 ページ に加えて、公式の ドキュメントJavadoc があります。 this one のようないくつかのビデオを見てみることもできます。これはRxの簡単な紹介で、RxとFuturesの違いについても述べています。

おまけ:Java 9 Reactive Streams

Java 9のReactive Streams aka Flow API は、 RxJava 2 のようなさまざまな Reactive Stream ライブラリによって実装されるインタフェースのセットです。 、 Akka Streams 、および Vertx 。これらは、すべての重要なバックプレッシャーを維持しながら、これらのリアクティブライブラリを相互接続することを可能にします。

226
Malt

私は0.9からRx Javaで働いていて、今は1.3.2で、すぐに2.xに移行しています。私はこれを私が既に8年間取り組んでいる私的プロジェクトで使います。

私はもうこのライブラリなしではプログラムしないでしょう。初めは私は懐疑的でしたが、それはあなたが創造する必要がある完全な他の心の状態です。初めは静かにしてください。私は時々ビー玉を何時間も見ていました..笑

それは単なる実務上の問題であり、実際にその流れ(オブザーバブルとオブザーバの契約)を知ることです。

私にとって、そのライブラリには本当にマイナス面はありません。

ユースケース:9つのゲージ(cpu、mem、networkなど)を含むモニタービューがあります。ビューを起動すると、ビューは9メートルのすべてのデータを含む観測可能値(間隔)を返すシステムモニタクラスに加入します。それは毎秒ビューに新しい結果をプッシュします(だからポーリングしません!!!)。このオブザーバブルはフラットマップを使用して9つの異なるソースからデータを同時に(非同期で)フェッチし、その結果をビューがonNext()で取得する新しいモデルに圧縮します。

どのようにしてあなたが未来や補完物などを使ってそれをやろうとしているのでしょう...頑張ってください! :)

Rx Javaは私のためにプログラミングの多くの問題を解決し、ある意味でずっと簡単になります...

利点:

  • Statelss !!! (言及するべき重要なこと、最も重要かもしれません)
  • すぐに使えるスレッド管理
  • 独自のライフサイクルを持つシーケンスを構築する
  • すべてが観測可能なので連鎖は簡単
  • 書くべきより少ないコード
  • クラスパス上の単一jar(非常に軽量)
  • 並行性が高い
  • もうコールバック地獄はありません
  • 加入者ベース(消費者と生産者間の密接な契約)
  • 背圧戦略(サーキットブレーカーなど)
  • 素晴らしいエラー処理と回復
  • とてもいいドキュメント(ビー玉<3)
  • 完全制御
  • もっと...

デメリット: - テストが難しい

16
Kristoffer