kotlin - 在 runBlocking 中使用 coroutineScope 有什么效果?
问题描述
在 kotlin coroutines doc中,它解释了“runBlocking 和 coroutineScope 之间的区别”:
范围构建器
除了不同构建器提供的协程作用域外,还可以使用 coroutineScope 构建器来声明自己的作用域。它创建了一个协程范围,并且在所有启动的子进程完成之前不会完成。
The main difference between runBlocking and coroutineScope is that the latter does not block the current thread while waiting for all children to complete
.
我不太明白,示例代码显示
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
}
日志:
2019-05-16 10:47:45.107 12239-12239 +++ before enter runBlocking{}
2019-05-16 10:47:45.219 12239-12239 +++ Task from coroutine scope
2019-05-16 10:47:45.320 12239-12239 +++ Task from runBlocking
2019-05-16 10:47:45.620 12239-12239 +++ Task from nested launch
2019-05-16 10:47:45.621 12239-12239 +++ ---after exit runBlocking{}
并且按预期+++ Task from nested launch
显示+++ Task from runBlocking
,因为它有 500L 延迟。
但是如果在块之后添加一些其他launch
的构建器coroutineScop{}
,结果会令人困惑。
这里有两个launch
是在coroutineScop{}
30L 和 100L 延迟之后添加的。
我期待看到延迟的日志30L
应该在 延迟300L
之前coroutineScop{}
出现launch
coroutineScop{}
fun testCoroutines() {
Log.e("+++", "+++ enter testCoroutines_3")
runBlocking {
launch {
println("+++ start Task from runBlocking, with 200L delay")
delay(200L)
println("+++ end Task from runBlocking, with 200L delay")
}
launch {
println("+++ start Task from runBlocking, with 50L delay")
delay(50L)
println("+++ end Task from runBlocking, with 50L delay")
}
launch {
println("+++ start Task from runBlocking, with 70L delay")
delay(70L)
println("+++ end Task from runBlocking, with 70L delay")
}
coroutineScope {
println("+++ enter Task from coroutineScope")
// Creates a coroutine scope
launch {
Log.v("+++", "+++ === start Task from nested launch, 500L")
delay(500L)
Log.v("+++", "+++ --- end Task from nested launch, 500L")
}
delay(100L)
println("+++ in Task from coroutineScope after delay(100L)")
launch {
Log.v("+++", "+++ === start Task from nested launch, 300L")
delay(300L)
Log.v("+++", "+++ --- end Task from nested launch, 300L")
}
println("+++ --- exit Task from coroutine scope") // This line will be printed before the nested launch
}
launch {
println("+++ start Task from runBlocking, with 30L delay")
delay(30L)
println("+++ end Task from runBlocking, with 30L delay")
}
launch {
println("+++ start Task from runBlocking, with 100L delay")
delay(100L)
println("+++ end Task from runBlocking, with 100L delay")
}
}
Log.e("+++", "--- exit testCoroutines_3 scope is over") // This line is not printed until the nested launch completes
}
日志:
10:35:05.819 4657-4657 +++ enter testCoroutines_3
10:35:05.828 4657-4657 +++ enter Task from coroutineScope
10:35:05.833 4657-4657 +++ start Task from runBlocking, with 200L delay
10:35:05.833 4657-4657 +++ start Task from runBlocking, with 50L delay
10:35:05.833 4657-4657 +++ start Task from runBlocking, with 70L delay
10:35:05.834 4657-4657 +++ === start Task from nested launch, 500L
10:35:05.885 4657-4657 +++ end Task from runBlocking, with 50L delay
10:35:05.905 4657-4657 +++ end Task from runBlocking, with 70L delay
10:35:05.932 4657-4657 +++ in Task from coroutineScope after delay(100L)
10:35:05.933 4657-4657 +++ --- exit Task from coroutine scope
10:35:05.935 4657-4657 +++ === start Task from nested launch, 300L
10:35:06.034 4657-4657 +++ end Task from runBlocking, with 200L delay
10:35:06.235 4657-4657 +++ --- end Task from nested launch, 300L
10:35:06.334 4657-4657 +++ --- end Task from nested launch, 500L
10:35:06.335 4657-4657 +++ start Task from runBlocking, with 30L delay
10:35:06.335 4657-4657 +++ start Task from runBlocking, with 100L delay
10:35:06.366 4657-4657 +++ end Task from runBlocking, with 30L delay
10:35:06.436 4657-4657 +++ end Task from runBlocking, with 100L delay
10:35:06.437 4657-4657--- exit testCoroutines_3 scope is over
认为至少+++ start Task from runBlocking, with 30L delay
应该在之后+++ === start Task from nested launch, 500L
和之前出现+++ end Task from runBlocking, with 50L delay
,但它并没有出现,毕竟launch
完成后+++ --- end Task from nested launch, 500L
。
协同程序块中的coroutineScope
做什么?
(我正在使用 android 应用程序进行测试,单击按钮调用testCoroutines
)
解决方案
coroutineScope
非阻塞的事实并不意味着它不等待其子协程完成。
事实上,两者runBlocking
都会coroutineScope
等待每个子协程完成后再完成。
两者之间的真正区别在于他们如何等待。runBlocking
阻塞当前线程,同时coroutineScope
挂起当前协程。
推荐阅读
- c++ - 你如何在 wxWidgets for C++ 中使用 SetTabBehaviour?
- java - 用Java制作链表
- python - 将多个表单中的数据保存在一页中
- java - 无法让 Spring Boot 应用程序在 Google Cloud Platform 柔性环境中运行
- mysql - centos中的mariadb远程连接失败
- javascript - GWT:使用纯 javascript 提取 textarea 值
- php - 多维数组上的 PHP array_merge
- eclipse - 我们可以从eclipse访问docker镜像、容器吗
- linux - 我推入 GITLAB 时出错(RPC 失败;HTTP 500 curl 22 The requested URL returned error: 500 Internal Server Error)
- spring-boot - 代号一个带有springboot服务器的RPC库