Kotlin协程runBlocking是否无论何种场景都会阻塞主线程?
关于runBlocking是否总会阻塞主线程的疑问与解答
疑问背景
runBlocking官方文档说明:
启动新协程并阻塞当前线程直至协程完成。该函数不应在协程内部使用,用于衔接常规阻塞代码与挂起风格的库,适用于主函数及测试场景。
据此我认为runBlocking仅阻塞当前线程。《Kotlin Coroutines Deep Dive》一书中提到:
"借助调度器,我们可以让runBlocking在不同线程运行,但启动该构建器的线程仍会被阻塞直至协程完成。"
我曾误解为即便通过withContext等方式切换至工作线程并在其中运行runBlocking,它仍会阻塞包括主线程在内的所有线程,因此想确认:无论采用何种方式,runBlocking是否总会阻塞主线程?
解答
runBlocking 只会阻塞调用它的那个线程,并非总会阻塞主线程,核心逻辑如下:
- 如果在主线程中调用runBlocking,那么主线程会被阻塞,直到内部协程执行完毕;
- 如果在子线程中调用runBlocking,那么只有调用它的这个子线程会被阻塞,主线程可以正常执行其他任务,完全不受影响;
- 书中所说的“借助调度器让runBlocking在不同线程运行”,指的是runBlocking内部的协程代码可以通过指定调度器(比如
Dispatchers.IO)在其他线程上执行,但调用runBlocking的原始线程仍然会被挂起等待,直到内部所有协程任务完成,这和“阻塞所有线程”完全是两回事。
举个简单示例:
fun main() { // 在主线程启动子线程 Thread { // 在子线程中调用runBlocking runBlocking(Dispatchers.IO) { delay(3000) println("runBlocking内部任务完成") } println("子线程执行完毕") }.start() // 主线程继续执行,不会被阻塞 println("主线程正在执行其他任务") Thread.sleep(4000) println("主线程执行完毕") }
这段代码中,runBlocking在子线程中调用,主线程不会被阻塞,会正常输出"主线程正在执行其他任务",等待3秒后子线程的runBlocking任务完成,最后主线程完成自己的延迟任务。
内容的提问来源于stack exchange,提问作者CodingBruceLee
相关产品推荐
相关产品推荐

