You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么runBlocking未阻塞当前线程?线程状态为RUNNABLE的原因

为什么runBlocking阻塞线程时,线程状态还是RUNNABLE而非BLOCKED?

根据官方文档描述,runBlocking会启动一个新协程并阻塞当前线程直至其完成,但运行以下代码时:

fun main() {
    println("Before runBlocking ${Thread.currentThread().state}")
    runBlocking {
        println("After runBlocking ${Thread.currentThread().state}")
    }
}

输出结果却是:

Before runBlocking RUNNABLE
After runBlocking RUNNABLE

这是因为这里的两个"阻塞"概念完全不同:

  • 线程的BLOCKED状态:是操作系统层面的线程状态,指线程因等待获取对象锁(比如进入synchronized块)而被挂起,此时线程不会被CPU调度执行。
  • runBlocking的"阻塞"语义:是协程框架层面的逻辑阻塞。runBlocking会将当前线程转换为协程的EventLoop调度器,线程并不会被操作系统挂起,而是进入一个主动循环,持续处理协程队列中的任务,直到所有子协程执行完毕。

简单来说,runBlocking并没有让线程进入操作系统级别的阻塞状态,线程一直在运行协程调度的循环逻辑,因此线程状态始终是RUNNABLE。

如果想直观看到线程进入BLOCKED状态,可以尝试让线程等待锁,比如:

val lock = Object()
fun main() {
    Thread {
        synchronized(lock) {
            Thread.sleep(1000)
        }
    }.start()
    Thread.sleep(100) // 确保另一个线程先拿到锁
    println("Before sync ${Thread.currentThread().state}")
    synchronized(lock) {}
    println("After sync ${Thread.currentThread().state}")
}

此时输出会显示线程进入BLOCKED状态,这才是操作系统定义的线程阻塞。

内容的提问来源于stack exchange,提问作者faritowich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 16:22:36