java中wait()不支持多级条件并行等待,需通过单一锁配多状态字段或reentrantlock配多个condition实现;必须用while循环检查条件、守锁操作、唤醒前更新状态;复杂场景推荐countdownlatch、cyclicbarrier或completablefuture等高级抽象。

Java 中 wait() 本身不支持“多级条件的并行等待”——它只是让当前线程在某个对象监视器上等待,直到被 notify() 或 notifyAll() 唤醒,或超时。所谓“多级条件”“并行等待”,实际是业务逻辑需求,需靠程序员用标准同步机制组合实现,而非 wait() 内置能力。
用单一锁 + 多条件变量(推荐)
一个 Object 锁可以配合多个布尔/枚举状态字段,线程根据各自关心的条件循环等待。关键在于:每次唤醒后都重新检查所有相关条件,避免虚假唤醒。
- 定义清晰的状态字段,例如:
isDataReady、isConfigLoaded、isShutdownRequested - 每个等待逻辑写成独立的
while (!condition) { wait(); }结构 - 状态变更后,优先用
notifyAll()(除非确定只有一个线程在等该条件),确保所有可能相关的等待线程都有机会重检
用 ReentrantLock + 多个 Condition 实现分离等待
比 synchronized + wait/notify 更灵活:一个锁可绑定多个 Condition,不同条件可独立 await() 和 signal(),避免无关线程被误唤醒。
- 创建
ReentrantLock lock = new ReentrantLock(); - 为各级条件分别定义:
Condition dataReady = lock.newCondition();、Condition configLoaded = lock.newCondition(); - 线程 A 等数据就绪:
lock.lock(); try { while (!dataReadyFlag) dataReady.await(); } finally { lock.unlock(); } - 另一线程更新数据后:
lock.lock(); try { dataReadyFlag = true; dataReady.signal(); } finally { lock.unlock(); }
避免常见陷阱
多条件协作时容易出错,核心原则是“守锁、查条件、等唤醒、再查”闭环不能断。
-
绝不裸调 wait():必须在
synchronized块或lock()保护下,且条件判断与wait()必须原子地处于同一临界区 -
不用 if 而用 while:因为
notifyAll()可能唤醒多个线程,而只有部分满足其目标条件;未满足者必须继续等 - 唤醒方要负责更新状态再 signal:顺序错误(先 signal 后改状态)会导致等待线程醒来后看到旧状态,再次陷入等待甚至死锁
更现代的替代思路
若场景复杂(如需等待多个异步事件汇合),直接用 wait/notify 易出错。可考虑更高层抽象:
-
CountDownLatch:适合“等待 N 个操作全部完成” -
CyclicBarrier:适合多线程互相等待到达某点 -
CompletableFuture:组合多个异步任务,用thenCombine、allOf表达条件依赖 - 消息队列或事件总线(如 Spring Event):解耦等待方与触发方,更适合松耦合的多级条件流
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











