wait方法定义在Object类而非Thread类,因为其本质是对象监视器(Monitor)机制的一部分,必须与对象锁强绑定:调用前需持有该对象锁,调用后释放锁并进入该对象的等待集(WaitSet),唤醒也针对特定对象,故逻辑上属于Object。

Java 中的 wait 方法本身**并不属于 JUC(java.util.concurrent)并发工具类**,而是 Object 类的原生方法,属于 JVM 层面的监视器(Monitor)机制。它在 JUC 工具类中**不直接出现**,但其底层思想和行为逻辑被深度借鉴、封装与替代——JUC 的设计目标之一,正是为了解决 wait/notify 使用复杂、易出错的问题。
wait 方法不在 JUC 类中直接调用
JUC 包下的核心同步工具(如 ReentrantLock、Condition、Semaphore、BlockingQueue 等)**完全不依赖 wait/notify**。它们基于 AQS(AbstractQueuedSynchronizer)实现,使用 LockSupport.park()/unpark() 进行线程阻塞与唤醒,底层走的是 Unsafe 操作和操作系统级线程调度,而非对象监视器队列(WaitSet)。
例如:
-
ReentrantLock.newCondition()返回的Condition对象,其await()和signal()行为语义上类比wait/notify,但内部调用的是 AQS 的等待队列 +LockSupport.park(); -
ArrayBlockingQueue的put()和take()方法在满/空时会阻塞,背后是Condition实例,不是synchronized + wait(); -
CountDownLatch.await()、CyclicBarrier.await()等也全部基于 AQS,无任何wait调用痕迹。
为什么 JUC 要绕开 wait?
wait/notify 存在几个硬伤,JUC 通过新机制规避:
立即学习“Java免费学习笔记(深入)”;
-
必须配合 synchronized:无法与显式锁(如
ReentrantLock)协同; -
虚假唤醒无法避免:只能靠
while循环防御,但Condition.await()同样要求while检查,不过语义更清晰; -
通知不可定向:
notify()随机唤醒,notifyAll()全体唤醒,而Condition支持多个独立等待队列,可精准signal()特定业务条件; -
异常侵入性强:
wait()声明抛出InterruptedException,且中断后需手动恢复中断状态,AQS 中的 park/unpark 对中断处理更统一可控。
wait 的“影子”仍存在于部分兼容场景
少数 JUC 工具类为兼容旧代码或简化实现,可能间接触发 wait,但属例外而非设计原则:
-
DelayQueue内部使用PriorityQueue,其迭代器在并发修改时可能抛出ConcurrentModificationException,但不涉及wait; -
ThreadPoolExecutor的awaitTermination()底层调用的是Condition.awaitNanos(),非Object.wait(); - 真正还用
wait的,基本只存在于java.lang或java.util的传统类(如Vector、Hashtable)及其遗留同步逻辑中,JUC 明确回避。
实际开发中该关注什么?
如果你在写并发逻辑,应优先掌握:
-
ReentrantLock + Condition替代synchronized + wait/notify; -
BlockingQueue(如LinkedBlockingQueue)封装生产者-消费者,无需手写wait; -
Phaser、Exchanger等高级协调器,比手动wait更安全、可读性更强; - 理解
LockSupport.park()是现代阻塞的基石,wait是它的“前辈”,但已非主流路径。


















