1. ホーム
  2. kotlin

[解決済み] コルーチン:runBlockingとcoroutineScopeの比較

2023-05-10 10:13:35

質問

私が読んでいたのは コルーチンの基本 を読んで、理解し、学ぼうとしています。

このコードでそこそこの部分があります。

fun main() = runBlocking { // this: CoroutineScope
    launch { 
        delay(200L)
        println("Task from runBlocking")
    }

    coroutineScope { // Creates a new coroutine scope
        launch {
            delay(900L) 
            println("Task from nested launch")
        }

        delay(100L)
        println("Task from coroutine scope") // This line will be printed before nested launch
    }

    println("Coroutine scope is over") // This line is not printed until nested launch completes
}

出力はこのようになります。

Task from coroutine scope
Task from runBlocking
Task from nested launch
Coroutine scope is over

質問ですが、なぜこの行なのでしょうか。

 println("Coroutine scope is over") // This line is not printed until nested launch completes

は常に最後に呼ばれるのですか?

の時から呼ばれるべきではないでしょうか?

coroutineScope { // Creates a new coroutine scope
    ....
}

は停止していますか?

そこには注意書きもあります。

runBlockingとcoroutineScopeの主な違いは、後者がすべての子プロセスの完了を待つ間、現在のスレッドをブロックしないことです。

coroutineScopeとrunBlockingがどう違うのか理解できませんが、coroutineScopeは最終行に到達して終了するので、ブロックしているように見えます。

誰かここで私を啓発することができますか?

ありがとうございます。

どのように解決するのですか?

<ブロッククオート

coroutineScopeとrunBlockingの違いがよくわかりません。 coroutineScopeは最終行に到達して初めて終了するので、ブロックしているように見えますが。

2つの別世界があります。 サスペンデッド の世界 (コルーチン内) と 非サスペンド のいずれかになります。の本体に入るとすぐに runBlocking の体内に入ると、そこはサスペンデッドな世界であり、そこでは suspend fun はブロッキングコードのように振る舞い、次の行に行くには suspend fun が戻るまで次の行に進めません。 coroutineScopesuspend fun で、その中の全てのコルーチンが終了したときにのみ戻るものです。したがって、最後の行は最後に表示されなければなりません。


私は、読者の間でクリックされたと思われるコメントから上記の説明をコピーしました。元の回答はこちらです。

ブロック内のコードの観点からは、あなたの理解は正しいです。の違いは runBlockingcoroutineScope はより低いレベルで起こります。コルーチンがブロックされている間、スレッドに何が起こっているのでしょうか?

  • runBlockingsuspend fun . これを呼び出したスレッドは、コルーチンが完了するまでその内部に残ります。

  • coroutineScopesuspend fun . コルーチンがサスペンドすると coroutineScope 関数も同様にサスペンドされます。これにより、トップレベルの関数である 非サスペンド 関数は同じスレッド上で実行を続けることができます。このスレッドでは coroutineScope ブロックを抜け出し、他の作業を行う準備ができています。

あなたの具体的な例では、あなたの coroutineScope が停止したとき、制御は runBlocking . このコードはイベントループで、その中で開始されたすべてのコルーチンを駆動します。あなたの場合、いくつかのコルーチンが遅延後に実行されるようにスケジュールされているでしょう。時間が来たら、適切なコルーチンを再開し、少しの間実行され、サスペンドされ、そして再び制御が内部に入るでしょう runBlocking .


上記は概念的な類似性を説明したものですが、同時に、以下のことも分かるはずです。 runBlocking 完全に異なる とは全く別のツールです。 coroutineScope .

  • runBlocking は低レベルの構成で、フレームワークのコードやあなたのような自己充足的な例でのみ使用されます。これは既存のスレッドをイベントループに変え、そのコルーチンを Dispatcher でそのコルーチンを作成し、イベントループのキューに再開するコルーチンをポストします。

  • coroutineScope はユーザー向けの構成要素で、その内部で並列分解されているタスクの境界を明確にするために使われます。これを使うと、便利なことに、すべての async の中で起きているすべての作業を待ち、最終的な結果を得て、 すべての失敗を一箇所で処理するのに便利です。