web-dev-qa-db-ja.com

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

kotlinx.coroutinesライブラリーでは、launchjoinを使用)またはasyncawaitを使用)を使用して新しいコルーチンを開始できます。それらの違いは何ですか?

97
Roman Elizarov
  • launch は、コルーチンの起動と破棄に使用されます。新しいスレッドを開始するようなものです。 launch内のコードが例外で終了する場合、スレッド内のuncaught例外のように扱われます-通常、バックエンドJVMアプリケーションのstderrに出力され、Androidがクラッシュします_アプリケーション。 join は、起動されたコルーチンの完了を待機するために使用され、例外を伝播しません。ただし、クラッシュしたchildコルーチンは、対応する例外でその親もキャンセルします。

  • async は、何らかの結果を計算するコルーチンを開始するために使用されます。結果は Deferred のインスタンスによって表され、あなたはmustawait を使用します。 asyncコード内のキャッチされない例外は、結果のDeferred内に格納され、他の場所には配信されません。処理されない限り、静かにドロップされます。 asyncで開始したコルーチンを忘れてはなりません。

149
Roman Elizarov

私はこのガイドを見つけました https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md は有用です。重要な部分を引用します

???? コルーチン

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

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

???? launch

fun main(args: Array<String>) {
    launch { // launch new coroutine in background and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello,") // main thread continues while coroutine is delayed
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}

したがって、launchはバックグラウンドスレッドを開始し、何かを実行し、Jobとしてすぐにトークンを返します。このjoinJobを呼び出して、このlaunchスレッドが完了するまでブロックできます。

fun main(args: Array<String>) = runBlocking<Unit> {
    val job = launch { // launch new coroutine and keep a reference to its Job
        delay(1000L)
        println("World!")
    }
    println("Hello,")
    job.join() // wait until child coroutine completes
}

???? async

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

したがって、asyncはバックグラウンドスレッドを開始し、何かを実行し、Deferredとしてすぐにトークンを返します。

fun main(args: Array<String>) = runBlocking<Unit> {
    val time = measureTimeMillis {
        val one = async { doSomethingUsefulOne() }
        val two = async { doSomethingUsefulTwo() }
        println("The answer is ${one.await() + two.await()}")
    }
    println("Completed in $time ms")
}

遅延値に対して.await()を使用して最終結果を取得できますが、遅延もジョブなので、必要に応じてキャンセルできます。

したがって、Deferredは実際にはJobです。 https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html を参照してください

interface Deferred<out T> : Job (source)

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

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

46
onmyway133