web-dev-qa-db-ja.com

KotlinコルーチンはRxKotlinよりも優れていますか?

Kotlinコルーチンを使用したいのはなぜですか?

RxKotlinライブラリはより汎用性が高いようです。 Kotlinコルーチンは、それほど強力ではなく、比較すると使用が面倒です。

Andrey Breslav(JetBrains)によるこのデザイントークのコルーチンに基づいて意見を述べています。 https://www.youtube.com/watch?v=4W3ruTWUhpw

トークのスライドショーはここからアクセスできます: https://www.slideshare.net/abreslav/jvmls-2016-coroutines-in-kotlin


編集(@hotkeyに感謝):

コルーチンの現在の状態に関するより良いソース: https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md

56
charlie_pl

Rxには2つの部分があります。 Observableパターン、およびそれらを操作、変換、結合するための演算子の強固なセット。 Observableパターン自体は、あまり効果がありません。コルーチンでも同じです。非同期性に対処するための単なる別のパラダイムです。特定の問題を解決するために、コールバック、Observable、コルーチンの長所/短所を比較できますが、完全な機能を備えたライブラリとパラダイムを比較することはできません。言語をフレームワークと比較するようなものです。

KotlinコルーチンはRxKotlinよりも優れていますか?コルーチンはまだ使用していませんが、C#のasync/waitに似ています。順次コードを書くだけで、非同期で実行する以外はすべて同期コードを書くのと同じくらい簡単です。把握しやすいです。

なぜコトリンコルーチンを使用したいのですか?私は自分で答えます。私はイベント駆動型のアーキテクチャを好むため、ほとんどの場合、Rxに固執します。しかし、シーケンシャルコードを記述し、途中で非同期メソッドを呼び出す必要がある状況が発生するはずです。コルーチンを喜んで活用して、Observableですべてをラップしないようにします。

編集:コルーチンを使用しているので、更新の時間です。

RxKotlinはKotlinでRxJavaを使用するための単なる構文上のシュガーなので、以下ではRxKotlinではなくRxJavaについて説明します。コルーチンは、RxJavaよりも下位のレバーでより一般的な概念であり、他のユースケースに役立ちます。とはいえ、RxJavaとコルーチン(channel)を比較できるユースケースが1つあり、データを非同期でやり取りしています。コルーチンには、ここでRxJavaよりも明確な利点があります。

コルーチンはリソースを扱う方が良い

  • RxJavaでは、スケジューラーに計算を割り当てることができますが、subscribeOn()ObserveOn()は混乱します。すべてのコルーチンにはスレッドコンテキストが与えられ、親コンテキストに戻ります。チャンネルの場合、両サイド(プロデューサー、コンシューマー)は自分のコンテキストで実行します。コルーチンは、スレッドまたはスレッドプールの影響についてより直感的です。
  • コルーチンは、それらの計算が発生するタイミングをより細かく制御します。たとえば、手渡し(yield)、優先順位付け(select)、並列化(複数のproducer/actor on channel)、またはリソースのロック(Mutex)特定の計算に対して。サーバー(RxJavaが最初に来た場所)では重要ではないかもしれませんが、リソースが限られた環境では、このレベルの制御が必要になる場合があります。
  • リアクティブな性質のため、バックプレッシャーはRxJavaにうまく適合しません。チャンネルのもう一方のsend()は、チャンネル容量に達すると一時停止する一時停止機能です。それは自然に与えられた、すぐに使える背圧です。 offer()をチャネルに送信することもできます。この場合、呼び出しは一時停止せず、チャネルがいっぱいの場合はfalseを返し、RxJavaからonBackpressureDrop()を効率的に再現します。または、独自のカスタムバックプレッシャーロジックを記述することもできます。これは、特にRxJavaで同じことを行う場合と比較して、コルーチンでは難しくありません。

コルーチンが輝く別のユースケースがあり、これは「なぜKotlinコルーチンを使用したいのですか?」という2番目の質問に答えます。コルーチンは、バックグラウンドスレッドまたはAsyncTask(Android)の完全な代替品です。 launch { someBlockingFunction() }と同じくらい簡単です。もちろん、おそらくSchedulersCompletableを使用して、RxJavaでもこれを実現できます。 RxJavaのシグネチャであるObserverパターンと演算子を使用しない(またはほとんど使用しない)。この作業はRxJavaの範囲外であるというヒントです。 RxJavaの複雑さ(ここでは役に立たない税)により、コードがより冗長になり、Coroutineのバージョンよりもクリーンでなくなります。

可読性が重要です。この点で、RxJavaとコルーチンのアプローチは大きく異なります。コルーチンはRxJavaよりも単純です。 map()flatmap()および一般的な関数型リアクティブプログラミングに慣れていない場合、基本的な手順を含むコルーチンの操作がより簡単になります:foriftry/catch ...しかし、私は個人的には、コルーチンのコードは自明ではないタスクでは理解しにくいと感じています。特に、RxJavaでの演算子チェーンによりすべてが揃うのに対し、より多くのネストとインデントが含まれます。関数型プログラミングにより、処理がより明確になります。その上、RxJavaは、豊富な(まあ、あまりにも豊富な)演算子セットからいくつかの標準演算子を使用して、複雑な変換を解決できます。 RxJavaは、多くの組み合わせと変換を必要とする複雑なデータフローがある場合に役立ちます。

これらの考慮事項が、ニーズに応じて適切なツールを選択するのに役立つことを願っています。

73
Geoffrey Marizy

KotlinコルーチンはRxとは異なります。 Kotlinコルーチンはシン言語機能であるため(2、3の基本概念とそれらを操作するためのいくつかの基本機能しかありません)、Rxは非常に多種多様な非常に重いライブラリであるため、それらを1対1で比較することは困難です。すぐに使用できるオペレーター。どちらも非同期プログラミングの問題に対処するように設計されていますが、ソリューションへのアプローチは大きく異なります。

  • Rxには、特定の機能スタイルのプログラミングが付属しており、言語自体のサポートなしで、実質的にすべてのプログラミング言語で実装できます。手元の問題が簡単に一連の標準演算子に分解される場合はうまく機能し、そうでない場合はうまく機能しません。

  • Kotlinコルーチンは、ライブラリライターが機能的リアクティブスタイル(Rx)などのさまざまな非同期プログラミングスタイルを実装できるようにする言語機能を提供します。 Kotlinコルーチンを使用すると、非同期コードを命令型スタイル、promise/futuresベーススタイル、アクタースタイルなどで記述することもできます。

RxとKotlinコルーチンに基づいて実装されている特定のライブラリを比較する方が適切です。

kotlinx.coroutines library を例に取ります。このライブラリは、async/awaitなどのプリミティブのセットと、通常は他のプログラミング言語に組み込まれているチャネルを提供します。また、軽量で未来のない俳優をサポートしています。詳しくは 例によるkotlinx.coroutinesのガイド をご覧ください。

kotlinx.coroutinesによって提供されるチャネルは、特定のユースケースでRxを置換または増強できます。別の コルーチンを使用したリアクティブストリームのガイド があり、Rxとの類似点と相違点がさらに深くなります。

74
Roman Elizarov

リンクしたトーク/ドキュメントは、チャンネルについては話していません。チャネルは、コルーチンの現在の理解とイベント駆動型プログラミングのギャップを埋めるものです。

コルーチンとチャネルを使用すると、rxを使用する場合と同じようにイベント駆動型プログラミングを実行できますが、同期的に見えるコードを使用して、多くの「カスタム」演算子を使用せずに実行できます。

これをよりよく理解したい場合は、kotlinの外側を検討することをお勧めします。kotlinでは、これらの概念はより成熟し洗練されています(実験的ではありません)。 Clojureのcore.async、リッチヒッキーの動画、投稿、関連するディスカッションをご覧ください。

4
Davide Bertola