news 2026/4/18 10:55:22

Java面试必看:notify()与notifyAll区别?点睛之笔!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java面试必看:notify()与notifyAll区别?点睛之笔!

文章目录

  • Java面试必看:notify()与notifyAll区别?点睛之笔!
    • 引言
    • 什么是 notify() 和 notifyAll()
      • 基本概念
    • 为什么会有 notify() 和 notifyAll()?
    • notify() 和 notifyAll() 的核心区别
      • 1. 唤醒范围不同
        • `notify()`:只唤醒一个线程
        • `notifyAll()`:唤醒所有线程
      • 2. 使用场景不同
        • `notify()` 的适用场景
        • `notifyAll()` 的适用场景
      • 3. 性能考虑
      • 4. 注意事项
      • 总结
    • 在实际开发中,合理选择 `notify()` 和 `notifyAll()` 对系统的性能和稳定性有重要影响。
      • 📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

Java面试必看:notify()与notifyAll区别?点睛之笔!

引言

大家好,我是闫工,今天我们要聊一个Java面试中经常被问到的考点——notify()notifyAll()的区别。这两个方法在多线程编程中非常重要,但它们的区别却常常让人一头雾水。别担心,我会用轻松幽默的方式为你详细解析,保证让你一学就会!


什么是 notify() 和 notifyAll()

在Java中,线程之间的通信离不开通知机制,而notify()notifyAll()就是实现这种机制的两个关键方法。它们都属于Object类,因此任何对象都可以调用这两个方法。

基本概念

  • notify(): 这个方法会唤醒一个正在等待该对象监视器的线程。
  • notifyAll(): 这个方法会唤醒所有正在等待该对象监视器的线程。

简单来说,notify()是“点名”叫醒某一个线程,而notifyAll()则是“广撒网”,把所有睡着的线程都叫醒。


为什么会有 notify() 和 notifyAll()?

在线程编程中,我们经常需要多个线程协作完成任务。比如生产者-消费者模型:一个或多个生产者线程负责生成数据,一个或多个消费者线程负责消费数据。如果没有通知机制,这些线程可能会陷入“忙等”状态,导致性能低下甚至死锁。

notify()notifyAll()的作用就是让线程之间能够高效地通信。通过它们,我们可以控制哪些线程被唤醒,从而优化程序的执行效率。


notify() 和 notifyAll() 的核心区别

1. 唤醒范围不同

notify():只唤醒一个线程

notify()会随机选择一个正在等待该对象监视器的线程,并将其唤醒。剩下的线程仍然保持阻塞状态,直到再次被通知或中断。

示例代码:

publicclassNotifyExample{publicstaticvoidmain(String[]args){Objectlock=newObject();// 创建多个线程for(inti=0;i<5;i++){newThread(()->{synchronized(lock){System.out.println(Thread.currentThread().getName()+" 进入等待状态");try{lock.wait();}catch(InterruptedExceptione){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+" 被唤醒");}}).start();}// 主线程通知newThread(()->{synchronized(lock){try{Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("主线程调用 notify()");lock.notify();// 只唤醒一个线程}}).start();}}

运行结果:

Thread-0 进入等待状态 Thread-1 进入等待状态 Thread-2 进入等待状态 Thread-3 进入等待状态 Thread-4 进入等待状态 主线程调用 notify() Thread-0 被唤醒

从结果可以看出,notify()只唤醒了一个线程(比如Thread-0),其他线程仍然处于阻塞状态。

notifyAll():唤醒所有线程

notifyAll()会将所有正在等待该对象监视器的线程都唤醒。这通常用于需要让所有线程继续执行的情况。

示例代码:

publicclassNotifyAllExample{publicstaticvoidmain(String[]args){Objectlock=newObject();// 创建多个线程for(inti=0;i<5;i++){newThread(()->{synchronized(lock){System.out.println(Thread.currentThread().getName()+" 进入等待状态");try{lock.wait();}catch(InterruptedExceptione){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+" 被唤醒");}}).start();}// 主线程通知newThread(()->{synchronized(lock){try{Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("主线程调用 notifyAll()");lock.notifyAll();// 唤醒所有线程}}).start();}}

运行结果:

Thread-0 进入等待状态 Thread-1 进入等待状态 Thread-2 进入等待状态 Thread-3 进入等待状态 Thread-4 进入等待状态 主线程调用 notifyAll() Thread-0 被唤醒 Thread-1 被唤醒 Thread-2 被唤醒 Thread-3 被唤醒 Thread-4 被唤醒

从结果可以看出,notifyAll()唤醒了所有线程。


2. 使用场景不同

notify()的适用场景

notify()适用于只需要唤醒一个线程的场景。例如:

  • 单生产者-多消费者模型:当一个生产者生成数据后,只需要通知一个消费者来处理。
  • 需要控制资源竞争的场景。

示例代码:

publicclassProducerConsumer{privateObjectlock=newObject();privatebooleanhasProduct=false;publicvoidproduce(){synchronized(lock){if(hasProduct){try{lock.wait();// 等待消费者消费}catch(InterruptedExceptione){e.printStackTrace();}}System.out.println("生产者生产了产品");hasProduct=true;lock.notify();// 唤醒一个消费者}}publicvoidconsume(){synchronized(lock){if(!hasProduct){try{lock.wait();// 等待生产者生产}catch(InterruptedExceptione){e.printStackTrace();}}System.out.println("消费者消费了产品");hasProduct=false;lock.notify();// 唤醒一个生产者}}publicstaticvoidmain(String[]args){ProducerConsumerpc=newProducerConsumer();// 创建多个消费者线程for(inti=0;i<3;i++){newThread(()->pc.consume()).start();}// 创建生产者线程newThread(()->{while(true){pc.produce();try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}}}).start();}}
notifyAll()的适用场景

notifyAll()适用于需要唤醒所有线程的场景。例如:

  • 所有线程都需要重新竞争资源。
  • 广播通知:比如某个条件满足后,所有线程都可以继续执行。

示例代码:

publicclassBroadcastExample{privateObjectlock=newObject();publicvoidcheckCondition(){synchronized(lock){System.out.println(Thread.currentThread().getName()+" 进入检查");if(!conditionMet()){// 假设条件未满足try{lock.wait();}catch(InterruptedExceptione){e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+" 条件满足,继续执行");}}publicvoidnotifyAllThreads(){synchronized(lock){System.out.println("设置条件为已满足");conditionMet();// 假设条件已满足lock.notifyAll();// 通知所有线程}}privatebooleanconditionMet(){returntrue;// 简化逻辑,假设条件已满足}publicstaticvoidmain(String[]args){BroadcastExampleexample=newBroadcastExample();// 创建多个检查线程for(inti=0;i<3;i++){newThread(()->example.checkCondition()).start();}// 主线程设置条件并通知所有线程newThread(()->example.notifyAllThreads()).start();}}

3. 性能考虑

  • notify()的性能更高,因为它只唤醒一个线程。
  • notifyAll()的性能较低,因为它需要唤醒多个线程。

因此,在大多数情况下,优先使用notify();只有在确实需要唤醒所有线程时才使用notifyAll()


4. 注意事项

  • 在调用wait()notify()方法时,必须持有同一对象的锁。
  • wait()必须在同步块中调用,否则会抛出IllegalMonitorStateException
  • 使用wait()notify()需要特别注意避免死锁和资源竞争问题。

总结

特性notify()notifyAll()
唤醒线程数1所有
使用场景单个唤醒广播通知
性能较低
资源竞争控制更好较差

在实际开发中,合理选择notify()notifyAll()对系统的性能和稳定性有重要影响。

📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

成体系的面试题,无论你是大佬还是小白,都需要一套JAVA体系的面试题,我已经上岸了!你也想上岸吗?

闫工精心准备了程序准备面试?想系统提升技术实力?闫工精心整理了1000+ 套涵盖前端、后端、算法、数据库、操作系统、网络、设计模式等方向的面试真题 + 详细解析,并附赠高频考点总结、简历模板、面经合集等实用资料!

✅ 覆盖大厂高频题型
✅ 按知识点分类,查漏补缺超方便
✅ 持续更新,助你拿下心仪 Offer!

📥免费领取👉 点击这里获取资料

已帮助数千位开发者成功上岸,下一个就是你!✨

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 8:43:09

基于django电信资费管理系统设计开发实现

电信资费管理系统的背景电信行业作为现代信息社会的基础设施&#xff0c;其资费管理直接关系到运营商的服务质量和用户满意度。传统资费管理多依赖手工操作或分散系统&#xff0c;存在效率低、易出错、难以实时更新等问题。随着电信业务复杂度提升&#xff08;如5G套餐、国际漫…

作者头像 李华
网站建设 2026/4/18 8:41:54

Kotaemon与Elasticsearch集成实现混合检索实战

Kotaemon与Elasticsearch集成实现混合检索实战 在企业级智能问答系统的开发中&#xff0c;一个反复出现的挑战是&#xff1a;如何让大模型既“懂行话”又不“胡说八道”。我们见过太多这样的场景——用户问“年假怎么申请”&#xff0c;系统却推荐起海南旅游攻略&#xff1b;或…

作者头像 李华
网站建设 2026/4/18 8:01:13

GSE宏编译器完全指南:从入门到精通魔兽世界技能编排

GSE宏编译器完全指南&#xff1a;从入门到精通魔兽世界技能编排 【免费下载链接】GSE-Advanced-Macro-Compiler GSE is an alternative advanced macro editor and engine for World of Warcraft. It uses Travis for UnitTests, Coveralls to report on test coverage and the…

作者头像 李华
网站建设 2026/4/18 8:44:26

终极Illustrator自动化脚本:35个高效工具完全指南

终极Illustrator自动化脚本&#xff1a;35个高效工具完全指南 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts 还在为重复的设计操作而烦恼吗&#xff1f;&#x1f914; 这个专为设计…

作者头像 李华
网站建设 2026/4/17 19:55:26

终极指南:用Apple Music-like Lyrics打造专业级歌词体验

终极指南&#xff1a;用Apple Music-like Lyrics打造专业级歌词体验 【免费下载链接】applemusic-like-lyrics 一个基于 Web 技术制作的类 Apple Music 歌词显示组件库&#xff0c;同时支持 DOM 原生、React 和 Vue 绑定。 项目地址: https://gitcode.com/gh_mirrors/ap/appl…

作者头像 李华
网站建设 2026/4/18 8:30:08

MZmine 3质谱分析完全攻略:从数据导入到结果解读的全流程实战

MZmine 3质谱分析完全攻略&#xff1a;从数据导入到结果解读的全流程实战 【免费下载链接】mzmine3 MZmine 3 source code repository 项目地址: https://gitcode.com/gh_mirrors/mz/mzmine3 MZmine 3作为一款功能强大的开源质谱数据分析软件&#xff0c;为科研人员提供…

作者头像 李华