调用 thread.sleep() 后线程状态从 runnable 进入 timed_waiting,这是 jvm 规范定义的、不释放锁的带超时等待状态,区别于 blocked(锁竞争)和 waiting(需同步上下文且释放锁)。

调用 Thread.sleep() 后,线程状态会从 RUNNABLE 进入 TIMED_WAITING,这是 JVM 规范明确定义的线程状态转换,不是“阻塞(BLOCKED)”或“等待(WAITING)”。
sleep() 对应的状态是 TIMED_WAITING,不是 BLOCKED
很多人误说“进入阻塞状态”,但 Java 的线程状态枚举中,BLOCKED 特指线程在尝试进入 synchronized 代码块/方法时,因锁被其他线程持有而**等待获取监视器锁**的状态。而 sleep() 是线程主动让出 CPU、不涉及锁竞争,它进入的是 TIMED_WAITING——一种带超时的等待状态。
-
TIMED_WAITING由Thread.sleep()、Object.wait(timeout)、LockSupport.parkNanos()等触发 - 可通过
thread.getState()实际验证:休眠中的线程返回的就是TIMED_WAITING - 该状态线程不参与 CPU 调度,但全程持有已获得的同步锁(与
wait()的行为关键不同)
调用栈底层走向影响状态切换时机,但不改变状态语义
当线程执行 Thread.sleep(1000),JVM 会将其转入 TIMED_WAITING,并最终通过系统调用(如 Linux 下的 nanosleep() 或 timerfd)交由内核定时唤醒。整个过程涉及:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- JVM 层面:更新线程状态为
TIMED_WAITING,记录休眠截止时间 - 本地方法层:调用 JNI 接口进入 OS 系统调用
- 内核调度层:线程被移出运行队列,挂起等待定时器事件
这个调用栈越深、上下文切换越多,实际唤醒延迟可能略高(尤其在高负载系统),但无论底层如何调度,对外暴露的线程状态始终是 TIMED_WAITING。
状态转换不可跳过,且无法被“跳过唤醒”
sleep() 的状态变化是原子且强制的:
- 一旦开始执行
sleep(),线程立刻脱离 RUNNABLE,不会停留在中间态 - 不能靠外部线程“直接拉回 RUNNABLE”;唯一合法中断方式是调用
interrupt(),此时抛出InterruptedException并立即转为 RUNNABLE(同时清中断标志) - 即使 CPU 空闲,线程也不会提前恢复——必须等满指定毫秒数,或被中断
和 yield()、wait() 的状态对比很关键
容易混淆的操作,状态差异明显:
-
yield():线程从 RUNNABLE → 仍为 RUNNABLE(只是主动让出时间片,回到就绪队列) -
wait():需在 synchronized 块内调用,RUNNABLE → WAITING,且自动释放锁 -
sleep():RUNNABLE → TIMED_WAITING,不释放任何锁,也不依赖同步上下文
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










