notify()无法指定唤醒特定线程,因其设计目标是通知至少一个等待线程,所有wait线程共用同一等待队列且jvm内部随机选择;需通过多锁对象、condition或状态变量+循环检查实现定向唤醒。

Java 中的 notify() 方法无法唤醒特定的线程或线程组合。
它只会随机唤醒一个正在该对象监视器(即 synchronized 锁对象)上等待(wait())的线程,且无法指定唤醒哪一个。这是由 JVM 实现决定的,不提供选择权。
为什么 notify 不能指定线程?
- `notify()` 的设计目标是**通知至少一个等待线程**,而非精确调度; - 所有调用 `wait()` 的线程都处于同一个等待队列(object's wait set),JVM 按内部策略(如 FIFO 或优先级)从中选一个; - Java 不暴露等待队列的结构,也不提供按条件、ID 或名称筛选线程的 API。想“唤醒特定线程”怎么办?
必须借助**应用层协调机制**,常见做法包括:-
使用多个独立锁对象,让不同线程组等待在不同对象上
private final Object lockGroupA = new Object(); private final Object lockGroupB = new Object(); // 线程 A 等待 synchronized (lockGroupA) { lockGroupA.wait(); } // 只唤醒 A 组线程 synchronized (lockGroupA) { lockGroupA.notify(); } -
使用
java.util.concurrent工具类替代原始 wait/notify-
Condition配合ReentrantLock,可为同一锁创建多个等待队列ReentrantLock lock = new ReentrantLock(); Condition condA = lock.newCondition(); Condition condB = lock.newCondition(); // 线程 A 等待 condA lock.lock(); try { condA.await(); } finally { lock.unlock(); } // 只唤醒等待 condA 的线程 lock.lock(); try { condA.signal(); } finally { lock.unlock(); }
-
-
用状态变量 + 循环检查实现逻辑上的“定向唤醒”
volatile boolean shouldWakeA = false; volatile boolean shouldWakeB = false; synchronized (lock) { while (!shouldWakeA) lock.wait(); // 线程 A 等待 } // 唤醒时设置标志再 notify shouldWakeA = true; synchronized (lock) { lock.notify(); }
notifyAll 是更安全的选择吗?
- `notifyAll()` 唤醒所有等待线程,但需配合 **while + 条件检查**(即“虚假唤醒”防护) - 它避免了因 `notify()` 随机唤醒导致“该醒的没醒、不该醒的醒了”的问题 - 在多数业务场景中,尤其涉及多个逻辑条件时,`notifyAll()` + 正确的条件判断比试图“精准唤醒”更可靠不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











