如何利用 Object 类的 waitnotify 方法实现基础线程间交互协作?
- 内容介绍
- 文章标签
- 相关推荐
本文共计729个文字,预计阅读时间需要3分钟。
可以使用 `Object` 类型的 `wait()` 和 `notify()`(或 `notifyAll()`)方法,在共享对象上建立等待-唤醒约定,实现线程间的基于状态的协作。核心在于:
共享状态对象作为协作枢纽
定义一个普通 Java 对象(如 class TaskQueue),封装被协作的业务状态(如任务列表是否为空、结果是否就绪)。这个对象既是数据载体,也是同步锁和通信媒介:
- 线程 A 调用
queue.wait()前,必须先获得queue的锁(synchronized(queue));它释放锁并进入等待队列,直到被唤醒 - 线程 B 修改状态后(如添加任务、设置结果),同样在
synchronized(queue)内调用queue.notify()或queue.notifyAll() - 被唤醒的线程重新竞争该对象锁,获取后继续执行——此时应重新检查条件(用 while 循环,不是 if),避免虚假唤醒
必须配合 while 循环做条件重检
wait() 可能被意外唤醒(如信号中断、JVM 唤醒),所以不能用 if (condition) wait();,而要用:
synchronized (sharedObj) { while (!conditionMet()) { sharedObj.wait(); } // 此时 conditionMet() 为 true,安全执行后续逻辑 }
例如生产者-消费者中,“队列非空”才是消费前提,消费者必须 while(!queue.isEmpty()) wait(); —— 即使被唤醒,也要再确认一次。
notify 与 notifyAll 的选择依据
notify() 随机唤醒一个等待线程,适用于“单一条件、唯一消费者/生产者”场景(如简单双线程交替打印);notifyAll() 唤醒所有等待线程,更安全通用,尤其当多个线程等待不同条件(如既有“非空”又有“未满”等待)时,由每个线程自行判断是否满足自身条件。
- 初学者建议统一用
notifyAll(),避免因唤醒错线程导致死锁 - 若明确只有一方在等某个条件,且能保证唤醒即满足,
notify()更轻量
典型协作模式示例:简单阻塞队列
以两个线程协作完成“生产一个、消费一个”为例:
- 生产者线程:获取锁 → 检查队列是否已满(while full)→ wait() → 添加元素 → notifyAll() → 释放锁
- 消费者线程:获取锁 → 检查队列是否为空(while empty)→ wait() → 取出元素 → notifyAll() → 释放锁
- 关键点:两次
notifyAll()都在修改状态后、同步块内调用;双方都用while重检条件
本文共计729个文字,预计阅读时间需要3分钟。
可以使用 `Object` 类型的 `wait()` 和 `notify()`(或 `notifyAll()`)方法,在共享对象上建立等待-唤醒约定,实现线程间的基于状态的协作。核心在于:
共享状态对象作为协作枢纽
定义一个普通 Java 对象(如 class TaskQueue),封装被协作的业务状态(如任务列表是否为空、结果是否就绪)。这个对象既是数据载体,也是同步锁和通信媒介:
- 线程 A 调用
queue.wait()前,必须先获得queue的锁(synchronized(queue));它释放锁并进入等待队列,直到被唤醒 - 线程 B 修改状态后(如添加任务、设置结果),同样在
synchronized(queue)内调用queue.notify()或queue.notifyAll() - 被唤醒的线程重新竞争该对象锁,获取后继续执行——此时应重新检查条件(用 while 循环,不是 if),避免虚假唤醒
必须配合 while 循环做条件重检
wait() 可能被意外唤醒(如信号中断、JVM 唤醒),所以不能用 if (condition) wait();,而要用:
synchronized (sharedObj) { while (!conditionMet()) { sharedObj.wait(); } // 此时 conditionMet() 为 true,安全执行后续逻辑 }
例如生产者-消费者中,“队列非空”才是消费前提,消费者必须 while(!queue.isEmpty()) wait(); —— 即使被唤醒,也要再确认一次。
notify 与 notifyAll 的选择依据
notify() 随机唤醒一个等待线程,适用于“单一条件、唯一消费者/生产者”场景(如简单双线程交替打印);notifyAll() 唤醒所有等待线程,更安全通用,尤其当多个线程等待不同条件(如既有“非空”又有“未满”等待)时,由每个线程自行判断是否满足自身条件。
- 初学者建议统一用
notifyAll(),避免因唤醒错线程导致死锁 - 若明确只有一方在等某个条件,且能保证唤醒即满足,
notify()更轻量
典型协作模式示例:简单阻塞队列
以两个线程协作完成“生产一个、消费一个”为例:
- 生产者线程:获取锁 → 检查队列是否已满(while full)→ wait() → 添加元素 → notifyAll() → 释放锁
- 消费者线程:获取锁 → 检查队列是否为空(while empty)→ wait() → 取出元素 → notifyAll() → 释放锁
- 关键点:两次
notifyAll()都在修改状态后、同步块内调用;双方都用while重检条件

