怎么通过 Object 类的 wait/notify 机制在面向对象层面实现初级的线程间协作
怎么通过 Object 类的 wait/notify 机制在面向对象层面实现初级的线程间协作

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
在Ja va多线程编程里,让线程之间有序协作,而不是乱成一锅粥,是个基本功。Object 类提供的 wait() 和 notify()(以及它的兄弟 notifyAll())方法,正是实现这种“等待-唤醒”契约的核心工具。简单来说,就是让一个线程在条件不满足时先“歇着”,等另一个线程准备好后再把它“叫醒”。
但这里有个铁律,必须牢记:所有对 wait 和 notify 的调用,都必须老老实实地放在 synchronized 同步块里,而且锁对象,必须就是调用这些方法的那个对象本身。这是整个机制能安全运转的基石。
共享状态对象作为协作枢纽
怎么理解这个“契约”呢?关键在于,要有一个共享的状态对象。你可以定义一个普通的Ja va类,比如叫 TaskQueue,用它来封装需要协作的业务状态——比如任务列表是不是空了,或者计算结果有没有准备好。这个对象身兼三职:它是数据的载体,是同步用的锁,更是线程间通信的“信号灯”。
- 线程A想调用
queue.wait()去等待,前提是它必须先拿到queue这把锁(也就是进入synchronized(queue)块)。一旦调用wait(),它就会释放锁,然后乖乖进入等待队列,直到被唤醒。 - 线程B在修改了共享状态(比如往队列里加了新任务)之后,同样需要在
synchronized(queue)块里,调用queue.notify()或queue.notifyAll()来发出信号。 - 被唤醒的线程(比如刚才的线程A)会重新加入竞争,去抢
queue的锁。抢到之后,它才能从wait()的地方继续执行。这里有个至关重要的细节:醒来后第一件事,应该是重新检查等待条件是否真的满足了。
必须配合 while 循环做条件重检
为什么必须重新检查?因为 wait() 存在“虚假唤醒”的可能性——线程可能因为某些与业务逻辑无关的原因(比如操作系统信号干扰)而被唤醒。所以,绝对不能简单地用 if 判断一次就了事,必须用 while 循环把等待条件包起来:
synchronized (sharedObj) {
while (!conditionMet()) { // 用while,不是if!
sharedObj.wait();
}
// 执行到这里时,conditionMet() 肯定为 true了,可以安全地处理后续逻辑
}
举个典型的例子,在生产者-消费者模型里,消费者线程能行动的前提是“队列非空”。所以,它的等待逻辑必须是 while(!queue.isEmpty()) wait(); —— 即使被唤醒了,也得再瞅一眼队列,确认真的有东西可消费才行。
notify 与 notifyAll 的选择依据
那么,叫醒一个线程,是用 notify() 还是 notifyAll() 呢?这得看场景。
notify()会随机唤醒等待在同一个对象上的一个线程。它适合条件单一、等待方角色明确的场景,比如两个线程严格交替执行。notifyAll()则更“豪爽”,它会唤醒所有正在等待的线程。这种方式更安全、更通用,尤其是在多个线程等待不同条件(比如有的在等“非空”,有的在等“未满”)的复杂场景下。唤醒后,让每个线程自己用while循环去判断是否满足了自己的条件,满足的就继续执行,不满足的继续等待。
对于初学者来说,有个实用的建议:如果不确定该用哪个,那就统一使用 notifyAll()。虽然可能带来一点点性能开销,但它能有效避免因唤醒错对象而导致的死锁风险。当然,如果你能百分之百确定,只有一类线程在等待某个条件,并且你一旦唤醒它,条件肯定满足,那么用 notify() 会更轻量一些。
典型协作模式示例:简单阻塞队列
理论说了这么多,来看一个最经典的“生产一个,消费一个”的协作模式,思路就非常清晰了:
- 生产者线程的行动路线是:获取锁 → 检查队列是否已满(用while循环判断)→ 如果满了就
wait()→ 添加元素 → 调用notifyAll()→ 释放锁。 - 消费者线程的行动路线是:获取锁 → 检查队列是否为空(同样用while循环判断)→ 如果空了就
wait()→ 取出元素 → 调用notifyAll()→ 释放锁。
这个模式里的关键点有两个:一是双方都在修改完共享状态后、离开同步块前调用 notifyAll();二是双方都坚持用 while 循环来重新检查等待条件。把握住这两点,一个基础的线程协作框架就搭建起来了。
相关攻略
VSCode无内置AI生成SQL能力,需依赖第三方扩展并连接外部模型服务;真正支持SQL生成的扩展仅有AskJina、GitHub Copilot和Ollama+Continue dev,且须正确配置上下文与提示词以保障生成质量。 开门见山地说,想在VSCode里让AI帮你写SQL,这事儿本身并不“
柴犬的 AI 升级:白皮书掀起销毁风暴! 柴犬(Shiba Inu)正在掀起一股新热潮。它早已不满足于网络迷因的标签,正全力构建一个拥有坚实技术愿景的加密生态系统。最近,一份关于人工智能的全新白皮书引爆了社区,其直接效应就是推动 SHIB 的销毁率大幅飙升。这背后究竟发生了什么?一起来深入看看。 A
Worldcoin (WLD) 面临趋势线阻力、战略合作推进及监管挑战:3 07美元的目标能否达成? Worldcoin(WLD)近期的市场表现,可以说牵动着不少投资者的神经。其价格正逼近一个至关重要的技术关口,而一系列战略动作与外部挑战交织,让“能否突破3 07美元”成为当前的核心悬念。 WLD价
JuCoin Labs 宣布战略投资越南协议创新项目 Spirit Deer 新一轮的DeFi浪潮正在酝酿,而这一次,焦点落在了可持续性与效率上。近日,JuCoin Labs宣布对越南创新项目Spirit Deer进行战略投资,这步棋被广泛视为推动去中心化金融向更稳健、更高效未来演进的关键信号。 J
怎么通过 Object 类的 wait notify 机制在面向对象层面实现初级的线程间协作 在Ja va多线程编程里,让线程之间有序协作,而不是乱成一锅粥,是个基本功。Object 类提供的 wait() 和 notify()(以及它的兄弟 notifyAll())方法,正是实现这种“等待-唤醒”
热门专题
热门推荐
荣耀Magic5录屏录音功能全解析:如何实现专业级音画同步 想在荣耀Magic5上录制带声音的屏幕内容?完全没问题。这款机型的录屏功能不仅支持录音,还给了你充分的选择权:可以只录系统内部播放的声音,比如游戏音效或视频原声;也可以只录制通过麦克风输入的人声解说;或者,两者混合录制,让讲解和演示声音同步
水空调如何更省电、更凉快?关键在于“精准控水、智能调风、协同环境”三位一体 想让水空调既省电又制冷强劲,秘诀不在于把水温调到最低,而在于一套“精准控水、智能调风、协同环境”的科学运行策略。简单来说,就是让水、风和环境三者打好配合。有实测数据表明,当循环水温稳定在7到12度这个“甜区”,配合高效的降温
卡萨帝洗衣机C9错误解析:排水异常背后的安全逻辑 当卡萨帝洗衣机的屏幕上跳出C9代码,很多用户的第一反应是“机器坏了”。其实不然,这恰恰是整机安全保护机制在起作用——它本质上是一个排水异常的硬件级提示。技术手册将其明确归类为“排水 进水时序异常”,意味着系统在脱水结束后,没能按预设剧本走完后续的进水
IH电饭煲煮的饭,真的更香吗? 答案是肯定的。无论是米饭的蓬松度、香气浓郁度、软硬均衡性,还是剩饭二次加热后的口感保持,IH电饭煲的表现通常都优于传统的底盘加热式电饭煲。这背后的核心,是一场从“局部加热”到“立体烹饪”的系统性技术升级。电磁感应技术让内胆自身均匀发热,结合精准的多段温度控制和部分机型
vivo S9恢复出厂设置失败,核心原因与标准处置流程 遇到vivo S9恢复出厂设置失败,先别急着下结论是手机坏了。这事儿,十有八九是操作链上的某个前置条件没达标——比如账户没退干净、电量告急,或者是系统缓存一时“卡了壳”。最稳妥的路径,依然是走系统设置菜单:依次点开【设置】→【系统管理】→【备份





