Timed_Waiting 状态的线程由系统按调用方法自动唤醒:sleep纯时间驱动;wait需超时、notify或中断任一条件;park可被unpark、超时或中断唤醒;并发工具类封装二者语义;须用while循环验证条件,警惕虚假唤醒。

线程处于 Timed_Waiting 状态时,唤醒时机由它当初调用的阻塞方法及其参数决定,不是由外部“触发”,而是由系统在满足特定条件后自动恢复线程调度。
看线程阻塞时调用的是哪个方法
不同方法进入 Timed_Waiting 的逻辑不同,唤醒机制也不同:
-
Thread.sleep(long millis):纯时间驱动。线程会在指定毫秒数(或纳秒补正后)到期时自动唤醒,不依赖其他线程操作;即使被中断,也会提前抛出InterruptedException并退出该状态。 -
Object.wait(long timeout):双条件唤醒。满足任一条件即唤醒:
– 超过timeout毫秒(计时到期);
– 其他线程在**同一对象上调用notify()或notifyAll()**(且本线程被选中);
– 当前线程被中断(抛出异常)。 -
LockSupport.parkNanos(long nanos)或parkUntil(long deadline):类似 sleep,但可被unpark()提前唤醒。唤醒条件包括:
– 时间到期;
– 其他线程对本线程调用LockSupport.unpark();
– 线程被中断。 -
java.util.concurrent工具类中的带超时方法(如BlockingQueue.poll(timeout, unit)、Future.get(timeout, unit)):底层通常封装了parkNanos或wait,唤醒逻辑遵循其封装的语义——超时、条件满足(如队列有数据、任务完成)、中断三者之一即可唤醒。
通过线程堆栈确认具体等待目标
JVM 能准确反映线程当前阻塞点。使用 jstack <pid></pid> 或 JVisualVM 查看线程栈,重点关注栈顶帧:
- 看到
java.lang.Thread.sleep(Native Method)→ 是sleep,只看时间。 - 看到
java.lang.Object.wait(long)→ 是wait,需结合锁对象和是否有 notify 发生来判断是否被信号唤醒。 - 看到
sun.misc.Unsafe.park(boolean, long)→ 大概率是parkNanos或并发工具类,需查代码上下文确认是否可能被unpark或超时唤醒。
注意“虚假唤醒”与唤醒后的检查义务
尤其对 wait() 和 park() 类方法,JVM 不保证唤醒一定对应真实事件(例如 wait 可能无通知就返回)。因此:
- 必须在
while循环中检查等待的条件是否真正成立,不能用if; - 不要假设唤醒 = 条件已满足,比如
queue.isEmpty() == false必须重新验证; - 超时唤醒也不代表操作成功,只是“等够了”,后续仍要处理失败路径(如返回 null、抛异常、重试等)。
调试建议:结合日志与监控
单纯靠状态判断不够,实际开发中可辅助以下手段:
- 在调用
wait/sleep/park前打日志,记录预期超时值、等待条件、时间戳; - 在唤醒后立刻记录实际耗时、唤醒原因(是否超时?是否收到 notify/unpark?是否中断?);
- 用
java.lang.management.ThreadInfo.getWaitedTime()(需开启 VM 监控)获取累计等待时间,辅助分析是否频繁超时或异常延迟。

















