Kotlinコルーチンでのlaunch / joinとasync / awaitの違いは何ですか



What Is Difference Between Launch Join



解決:

  • 打ち上げは ファイアアンドフォーゲットコルーチン 。これは、新しいスレッドを開始するようなものです。内部のコードが起動は例外で終了し、次のように扱われます 捕まえられない スレッドの例外-通常、バックエンドJVMアプリケーションでstderrに出力され、Androidアプリケーションがクラッシュします。joinは、起動されたコルーチンの完了を待機するために使用され、例外を伝播しません。しかし、墜落した 子供 コルーチンは、対応する例外を除いてその親もキャンセルします。

  • 非同期は いくつかの結果を計算するコルーチンを開始します 。結果は、次のインスタンスで表されます。延期され、あなた しなければならない 使用するそれを待っています。内部のキャッチされない例外非同期コードは、結果の内部に保存されます延期され、他の場所に配信されないため、処理されない限り、サイレントにドロップされます。 asyncで始めたコルーチンを忘れてはなりません




このガイドhttps://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.mdが役立つと思います。本質的な部分を引用します

コルーチン



基本的に、コルーチンは軽量のスレッドです。

したがって、コルーチンは非常に効率的な方法でスレッドを管理するものと考えることができます。

発売



fun main(args:Array){launch {//バックグラウンドで新しいコルーチンを起動して続行delay(1000L)// 1秒間の非ブロッキング遅延(デフォルトの時間単位はms)println( 'World!')//後に​​出力delay} println( 'Hello、')//コルーチンが遅延している間メインスレッドは続行しますThread.sleep(2000L)// JVMを存続させるためにメインスレッドを2秒間ブロックします}

そうlaunchはバックグラウンドスレッドを開始し、何かを実行し、次のようにすぐにトークンを返します。仕事。あなたは呼び出すことができますこれに参加するこれまでブロックするジョブ起動スレッドが完了します

fun main(args:Array)= runBlocking {val job = launch {//新しいコルーチンを起動し、そのジョブへの参照を保持しますdelay(1000L)println( 'World!')} println( 'Hello、')job.join( )//子コルーチンが完了するまで待つ}

非同期

概念的には、非同期は起動と同じです。これは、他のすべてのコルーチンと同時に機能する軽量スレッドである別のコルーチンを開始します。違いは、launchはジョブを返し、結果の値を運ばないのに対し、asyncはDeferredを返すことです。これは、後で結果を提供するという約束を表す軽量のノンブロッキングフューチャーです。

そうasyncはバックグラウンドスレッドを開始し、何かを実行し、次のようにすぐにトークンを返します。延期。

fun main(args:Array)= runBlocking {val time = measureTimeMillis {val one = async {doSomethingUsefulOne()} val two = async {doSomethingUsefulTwo()} println( '答えは$ {one.await()+ two.awaitです()} ')} println(' $ time msで完了 ')} 

延期された値で.await()を使用して最終的な結果を取得できますが、Deferredはジョブでもあるため、必要に応じてキャンセルできます。

そう延期は実際には仕事。 https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.htmlを参照してください

インターフェース延期:ジョブ(ソース)

非同期はデフォルトで熱心です

CoroutineStart.LAZYの値を持つオプションの開始パラメーターを使用して非同期化する遅延オプションがあります。コルーチンを開始するのは、その結果が待機によって必要になった場合、または開始関数が呼び出された場合のみです。


起動してasyncは、新しいコルーチンを開始するために使用されます。しかし、彼らはそれらを異なる方法で実行します。

違いを簡単に理解するのに役立つ非常に基本的な例を示したいと思います

  1. 発売
class MainActivity:AppCompatActivity(){override fun onCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)btnCount.setOnClickListener {pgBar.visibility = View.VISIBLE CoroutineScope(Dispatchers.Main).launch {val currentMillis = System.currentTimeMillis()val retVal1 = downloadTask1()val retVal2 = downloadTask2()val retVal3 = downloadTask3()Toast.makeText(applicationContext、 'すべてのタスクがダウンロードされました!$ {retVal1}、$ {retVal2}、$ { retVal3} in $ {(System.currentTimeMillis()-currentMillis)/ 1000}秒 '、Toast.LENGTH_LONG).show(); pgBar.visibility = View.GONE}} //タスク1は、ダウンロードを完了するのに5秒かかりますprivate suspend fun downloadTask1():String {kotlinx.coroutines.delay(5000); '完了'を返します。 } //タスク1は、ダウンロードを完了するのに8秒かかりますprivate suspend fun downloadTask2():Int {kotlinx.coroutines.delay(8000); 100を返します。 } //タスク1は、ダウンロードを完了するのに5秒かかりますprivate suspend fun downloadTask3():Float {kotlinx.coroutines.delay(5000); 4.0fを返します。 }}

この例では、私のコードはクリックすると3つのデータをダウンロードしていますbtnCountボタンと表示すべてのダウンロードが完了するまで、pgBarプログレスバー。 3つあります関数を一時停止しますdownloadTask1()、downloadTask2()およびデータをダウンロードするdownloadTask3()。それをシミュレートするために、私は使用しましたこれらの関数のdelay()。これらの関数は待機します5秒、8秒とそれぞれ5秒。

私たちが使用したようにこれらのサスペンド機能を開始するための起動、起動するとそれらが実行されます 順次(1つずつ) 。この意味は、downloadTask2()は後に開始されますdownloadTask1()が完了し、downloadTask3()は、downloadTask2()が完了します。

出力スクリーンショットのように乾杯、3つのダウンロードすべてを完了するための合計実行時間は 5秒+8秒+5秒= 18秒発売

起動例

  1. 非同期

私たちが見たように起動すると実行されます3つのタスクすべてに対して順番に。すべてのタスクを完了する時間は18秒。

それらのタスクが独立していて、他のタスクの計算結果を必要としない場合は、それらを実行させることができます同時に。それらは同時に開始し、バックグラウンドで同時に実行されます。これはで行うことができます非同期。

asyncはのインスタンスを返しますデファードタイプ、ここでTは、サスペンド関数が返すデータのタイプです。例えば、

  • downloadTask1()は文字列は関数の戻り型であるため、延期されます
  • downloadTask2()はIntは関数の戻り型であるため、延期されます
  • downloadTask3()はFloatは関数の戻り型であるため、延期されます

からの戻りオブジェクトを使用できますタイプの非同期で戻り値を取得するために延期Tタイプ。それはで行うことができますawait()呼び出し。たとえば、以下のコードを確認してください

btnCount.setOnClickListener {pgBar.visibility = View.VISIBLE CoroutineScope(Dispatchers.Main).launch {val currentMillis = System.currentTimeMillis()val retVal1 = async(Dispatchers.IO){downloadTask1()} val retVal2 = async(Dispatchers.IO ){downloadTask2()} val retVal3 = async(Dispatchers.IO){downloadTask3()} Toast.makeText(applicationContext、 'ダウンロードされたすべてのタスク!$ {retVal1.await()}、$ {retVal2.await()}、$ {retVal3.await()} in $ {(System.currentTimeMillis()-currentMillis)/ 1000}秒 '、Toast.LENGTH_LONG).show(); pgBar.visibility = View.GONE}

このようにして、3つのタスクすべてを同時に起動しました。したがって、完了するまでの合計実行時間はの時間である8秒downloadTask2()は、3つのタスクすべての中で最大です。これは、次のスクリーンショットで確認できます。トーストメッセージ

例を待つ