kotlin - 协程 : runBlocking vs coroutineScope

我正在阅读 Coroutine Basics试图理解和学习它。

这里有一段代码:

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
    ....
}

被暂停了?

那里还有一个注释:

The main difference between runBlocking and coroutineScope is that the latter does not block the current thread while waiting for all children to complete.

我不明白 coroutineScope 和 runBlocking 在这里有何不同? coroutineScope 看起来像它的阻塞,因为它只在完成后才到达最后一行。

有人能告诉我吗?

提前致谢。

最佳答案

I don't understand how coroutineScope and runBlocking are different here? coroutineScope looks like its blocking since it only gets to the last line when it is done.

有两个独立的世界:可暂停世界(在协程内)和不可暂停世界。一旦你进入 runBlocking 的主体,你就进入了可暂停的世界,suspend fun 的行为就像阻塞代码一样,直到你无法进入下一行suspend fun 返回。 coroutineScope 是一个 suspend fun,仅当其中的所有协程完成时才返回。因此最后一行必须打印在最后。


我从似乎受到读者点击的评论中复制了上述解释。这是原始答案:

从block中的代码来看,你的理解是正确的。 runBlockingcoroutineScope 的区别发生在较低的层次:当协程被阻塞时线程发生了什么?

  • runBlocking 不是 suspend fun。调用它的线程会一直留在其中,直到协程完成。

  • coroutineScope 是一个暂停乐趣。如果你的协程挂起,coroutineScope 函数也会被挂起。这允许顶层函数,一个创建协程的非挂起函数,继续在同一个线程上执行。线程已经“转义”了 coroutineScope block 并准备好做一些其他工作。

在您的具体示例中:当您的 coroutineScope 暂停时,控制权返回到 runBlocking 内的实现代码。这段代码是一个事件循环,它驱动你在其中启动的所有协程。在您的情况下,将有一些协程计划在延迟后运行。时间到了会恢复相应的协程,运行一小会儿,挂起,然后控制又回到runBlocking里面。


虽然上面描述了概念上的相似之处,但它也应该向您展示 runBlocking 是一个与 coroutineScope 完全不同的工具

  • runBlocking 是一个低级结构,仅用于框架代码或像您这样的自包含示例。它将现有线程转换为事件循环,并使用 Dispatcher 创建其协程,将恢复的协程发布到事件循环的队列中。

  • coroutineScope 是一个面向用户的构造,用于描绘在其中被并行分解的任务的边界。您可以使用它方便地等待其中发生的所有 async 工作,获得最终结果,并在一个中心位置处理所有故障。

https://stackoverflow.com/questions/53535977/

相关文章:

kotlin - 让 Kotlin 在将灵活/平台类型分配给非空类型时发出警告?

eclipse - 无法在 Eclipse 中运行 Kotlin 应用程序

rx-java - Kotlin 和 RxJava - 为什么我的 Single.zip() 没有编

java - java 10 和 kotlin 中的 “var”

kotlin - 0xFF0000FF 整数文字不符合预期的类型 kotlin.Int

kotlin - 什么是 Kotlin 模块?

arrays - Kotlin 中的二维数组

android - Kotlin 和惯用的编写方式, 'if not null, else...'

kotlin - 如何在 Kotlin 中运行编译的类文件?

kotlin - 检查 Kotlin 中的字符串是否为空