协程范围构建器流程如何工作

时间:2020-05-01 15:17:43

标签: kotlin kotlin-coroutines

科特琳说

  • runBlocking方法阻止当前线程等待
  • coroutineScope只是挂起,释放了底层线程供其他用途。
  • 因此,runBlocking是常规函数,而coroutineScope是挂起函数
fun main() = runBlocking { // this: CoroutineScope
    launch { 
        delay(200L)
        println("Task from runBlocking")
    }

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

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

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

在上面的示例中,我期望的是:-

  • runBlocking阻塞主线程,launch将被执行,并涉及delay(200L)
  • 因此,底层协程被释放并运行coroutineScope并到达delay(500L)delay(100L)
  • 因此,再次释放了底层协程,它应打印println("Coroutine scope is over")

这就是我对runBlockingcoroutineScope的理解。哪个无法正常工作。

输出为

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

任何人都可以通过一种简单的方式来理解它。

2 个答案:

答案 0 :(得分:2)

launch导致该块异步执行 ,因此对launch的调用会立即返回,协程将继续运行,而不会等待执行启动的区块。

因此,在调用runBlocking之后,立即依次调用第一个launch和第二个delay(100L),并在此之后立即将协程暂停在{{1}}上。

100毫秒后,协程将恢复并打印“协程作用域中的任务”,然后嵌套的协程作用域范围的块的执行结束。协程范围始终等待它启动的所有作业的执行结束,因此在这里等待500ms。

同时,将执行两个启动的块,因此首先打印“ runBlocking的任务”(从开始200毫秒后),然后打印“嵌套启动的任务”(从开始500毫秒后)。

最终,内部启动作业完成后,内部协同程序范围结束等待,外部协同程序继续并打印“协同程序范围已结束”。

这是故事。我希望这对理解代码的执行方式以及打印顺序为何如此有帮助。

答案 1 :(得分:1)

我对您的代码做了一些修改

fun main() = runBlocking(Dispatchers.Default) {

    var i = 1
    launch {
        println("Task from runBlocking")
        while (i < 10) {
            delay(30L)
            println(i++)
        }
    }

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

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

    println("Coroutine scope is over")

}

输出

Task from runBlocking
1
2
3
Task from coroutine scope
4
5
6
Task from nested launch
Coroutine scope is over
7
8
9

我的观察结果是

  • 延迟(100L)大约等于延迟(30L)的3倍

  • 延迟(200L)大约等于延迟(30L)的6倍

因此,在打印3 Task from coroutine scope之后和6 Task from nested launch之后。

然后恰好在此Coroutine scope is over之后,但是您仍然可以看到循环打印的7,8,9

这是因为像runBlocking coroutineScope那样,它通过挂起基础线程来等待其所有成员执行。但是请理解,这些线程首先在coroutineScope的成员上工作,而不是在runBlocking的成员上工作。

因此,它正在Task from coroutine scope之前打印Task from nested launchCoroutine scope is over