了解 runBlocking 和 coroutineScope 之间的行为差​​异

时间:2021-02-27 15:18:49

标签: kotlin asynchronous concurrency parallel-processing kotlin-coroutines

在 Kotlin 协程指南 here 中,在解释 runBlockingcoroutineScope 之间的区别时,它说:

<块引用>

... 主要区别在于 runBlocking 方法阻塞当前线程等待,而 coroutineScope 只是挂起,释放底层线程用于其他用途。 ...

这是可以理解的。但是,在此处列出的示例代码中:

import kotlinx.coroutines.*

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
}

产生以下输出:

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

coroutineScope 替换 runBlocking 为:

import kotlinx.coroutines.*

fun main() = runBlocking { // this: CoroutineScope
    launch { 
        delay(200L)
        println("Task from runBlocking")
    }
    
    runBlocking { // instead of coroutineScope, previously
        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 会阻塞,直到它的块完成,包括所有子协程:

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

有人可以解释这种行为吗?我在这里监督什么?

2 个答案:

答案 0 :(得分:3)

在 runBlocking 中包含 runBlocking 是.. 不寻常的。更常见的是 runBlocking 只是最外层的东西。实际上,runBlocking 的实现将使用外部 runBlocking 的事件循环而不是创建一个新的事件循环,因此在这种情况下,它实际上表现得像 coroutineScope。

来源:https://github.com/Kotlin/kotlinx.coroutines/blob/dda99e21f45f65eb540ccf4d5e82faf7559bc9e5/kotlinx-coroutines-core/jvm/src/Builders.kt#L46

答案 1 :(得分:0)

runBlocking 只是阻塞当前线程,直到传递给它的 block 返回。它不会影响 block 的执行方式。