Kotlin协程技术疑问:挂起函数运行在哪个线程?
Kotlin协程挂起函数恢复后的线程归属问题
你的观察完全正确:挂起函数在完成挂起操作(比如delay)后,后续代码会运行在调用它的协程所绑定的调度器对应的线程上。
核心原理
协程的执行线程由它的**调度器(Dispatcher)**决定。当调用挂起函数导致协程挂起时,协程会让出当前线程;当挂起操作完成后,协程会自动在原调度器管理的线程(或线程池中的线程)上恢复执行,所以挂起函数内挂起操作之后的代码,会和调用它的协程保持相同的线程上下文(除非主动切换调度器)。
结合你的代码分析
你的实验代码运行逻辑如下:
import kotlinx.coroutines.* fun main(): Unit = runBlocking { println("parent ${Thread.currentThread().name}") test() launch (Dispatchers.IO) { println("parent2 ${Thread.currentThread().name}") test2() } } suspend fun test() { delay(1) println("child ${Thread.currentThread().name}") //Who processes this? } suspend fun test2() { delay(1) println("child2 ${Thread.currentThread().name}") //Who processes this? }
runBlocking默认使用当前的main线程作为协程执行线程,所以test函数中delay恢复后,println会在main线程执行,输出类似child main。launch(Dispatchers.IO)创建的协程绑定了IO调度器,它会使用IO线程池中的线程执行,所以test2中delay恢复后,println会在IO线程池的某个线程执行,输出类似child2 DefaultDispatcher-worker-1(线程编号可能不同)。
例外情况:主动切换调度器
如果挂起函数内部使用withContext主动切换调度器,后续代码会在新调度器的线程上执行,比如:
suspend fun test3() { delay(1) withContext(Dispatchers.Default) { println("child3 ${Thread.currentThread().name}") // 运行在Default调度器的线程 } }
这种情况下,withContext块内的代码会切换到指定调度器线程执行,但块外的代码仍会回到原协程的调度器线程。
内容的提问来源于stack exchange,提问作者Tony Chen
相关产品推荐
相关产品推荐

