notify()仅改变线程状态为blocked,不保证及时执行;真正运行需满足锁释放、cpu调度、成功争锁三条件,延迟常源于同步块过长、调度不公或条件未重检。

Java 中 notify() 方法本身并不保证唤醒的及时性,它只负责“发信号”,不控制调度、不释放锁、也不决定被唤醒线程何时真正执行。所谓“及时”,取决于多个底层环节的配合,而非 notify 单独能实现。
notify 不直接触发执行,只是改变线程状态
调用 notify() 后,JVM 仅从该对象的等待队列中随机选一个线程,将其状态从 WAITING 改为 BLOCKED(即进入锁竞争队列),但该线程仍需等待以下条件全部满足才能继续运行:
- 当前持有锁的线程必须退出 synchronized 块(锁被释放)
- CPU 调度器分配时间片给该线程(可能被其他高优先级线程抢占)
- 该线程成功争抢到对象锁(若多个线程同时被 notify 或 notifyAll,存在竞争)
影响“及时性”的关键因素
实际响应快慢受以下现实因素制约:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 锁持有时间过长:若 notify() 所在的同步块执行耗时(如含 I/O、计算或 sleep),被唤醒线程会卡在 BLOCKED 状态,无法及时进入运行
- 线程优先级与调度策略:JVM 不保证公平调度,低优先级线程即使被唤醒,也可能长期得不到 CPU 时间
- 虚假唤醒或条件未就绪:被唤醒线程若未用 while 循环重检条件,可能发现资源仍未可用,又得 wait() 回去,造成“唤醒→检查→再等待”的延迟假象
- 等待线程数量多但只 notify 一个:比如 10 个消费者都在等数据,notify() 只唤醒其一;其余仍阻塞,下次生产后需再次 notify —— 这不是 notify 不及时,而是设计上本就不面向批量通知
提升响应效率的实际做法
与其依赖 notify “变快”,不如优化协作逻辑,让唤醒后能尽快推进:
- 保持 synchronized 块尽量短:只做必要状态变更和 notify,把耗时操作移出同步区
- 始终用 while(!condition) { wait(); },避免因条件未满足而空转或重复等待
- 确认唤醒目标唯一且必要:例如一对一管道通信中,notify 安全高效;若多线程依赖同一条件(如缓冲区非空),应优先考虑 notifyAll()
- 避免在 notify 后立即 return 或抛异常:确保 notify 发出后,相关状态已稳定、后续逻辑无风险
不要混淆“唤醒”和“执行”
notify() 是“通知等待者可以来抢锁了”,不是“现在就让你运行”。真正的执行时机由 JVM 线程调度器决定,不受 Java 代码直接控制。如果你观察到唤醒延迟明显,问题通常不在 notify 本身,而在锁竞争激烈、同步块臃肿,或条件判断逻辑不合理。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










