kotlin - 使用 withContext 的协程执行顺序
问题描述
几天前我开始研究协程。我明白了一点,但后来我看到一些代码行提出了一些问题:
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
println("in sub coroutine ${Thread.currentThread().name}")
}
println("before coroutine in main ${Thread.currentThread().name}")
withContext(Dispatchers.IO) {
println("hello from coroutine ${Thread.currentThread().name}")
delay(1500)
println("hello from coutoutine after delay ${Thread.currentThread().name}")
}
println("after coroutine in main ${Thread.currentThread().name}")
}
输出是:
before coroutine in main main @coroutine#1
in sub coroutine main @coroutine#2
hello from coroutine DefaultDispatcher-worker-1 @coroutine#1
hello from coutoutine after delay DefaultDispatcher-worker-1 @coroutine#1
after coroutine in main main @coroutine#1
据我了解,launch
在工作线程上创建一个新的协程,因此主线程上的任何正常功能都会在启动完成之前执行。如果是这样,我有点困惑为什么代码在代码之前withContext
运行。有人可以解释吗?launch
解决方案
launch
在工作线程上创建一个新的协程
当你按照这样的句子构筑你的想法时要小心。协程不像普通代码那样在给定线程上运行。这更像是将线程固定到 CPU 内核。固定线程不拥有内核,操作系统只是确保,无论何时挂起然后恢复它,它都会将其调度到同一个 CPU 内核。
如果您使用“将线程调度到 CPU 内核”范式浏览您的代码,您可以很容易地看到您的输出是如何有意义的:
runBlocking { // Create a context within which "threads" are pinned
// to a single "core", let's call it "Main Core"
launch { // Start another "thread" pinned to "Main Core". The "thread" is
// in a suspended state, waiting for "Main Core" to get free
println("in sub coroutine ${Thread.currentThread().name}")
}
// `launch` is just a function, it completed after creating the new "thread",
// move on to the code below it
println("before coroutine in main ${Thread.currentThread().name}")
// Start a context where "threads" are pinned to another "core", the
// "IO Core". It executes its "threads" concurrently to "Main Core".
// However, the particular "thread" that creates the context gets suspended
// until it is done. Other "threads" pinned to "Main Core" can run.
withContext(Dispatchers.IO) {
println("hello from coroutine ${Thread.currentThread().name}")
delay(1500)
println("hello from coutoutine after delay ${Thread.currentThread().name}")
}
// Now the "thread" that created the "IO Core" context can go on.
println("after coroutine in main ${Thread.currentThread().name}")
}
在这张图片中,您只需添加一个事实,即“OS”无法抢先挂起“线程”,只有当“线程”挂起自己时,“OS”才能接管以做出另一个调度决定。
推荐阅读
- json - 如何从逻辑应用中的 Azure Blob 存储文件解析 JSON?
- html - 如何通过 css(beautiful-jekyll 主题)修改标题颜色?
- swift - Swift 中的 Post Feed 数据建模
- php - 如何用值数组替换数组中的值
- outlook - 右键单击上下文未显示在 Outlook 加载项上
- python - 如何在函数中编辑变量,而不是将其传递给另一个函数?
- git - 二进制文件和“* text eol=lf”
- javascript - Nextjs 在 app.prepare().then() 中使用 Promise 时出错:getaddrinfo ENOTFOUND undefined
- python - 编写一个名为 get_first_capital(word) 的递归函数,它接受一个字符串作为参数
- refactoring - 如何分解 imacro 脚本?