如何利用 Object 类的 waitnotify 方法实现基础线程间交互协作?

2026-05-03 01:493阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计729个文字,预计阅读时间需要3分钟。

如何利用 Object 类的 wait/notify 方法实现基础线程间交互协作?

可以使用 `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 重检条件
标签:AI

本文共计729个文字,预计阅读时间需要3分钟。

如何利用 Object 类的 wait/notify 方法实现基础线程间交互协作?

可以使用 `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 重检条件
标签:AI