news 2026/4/3 3:16:35

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/3/27 16:48:43

17、网络犯罪检测技术:从日志审计到入侵检测

网络犯罪检测技术:从日志审计到入侵检测 在当今数字化时代,网络安全至关重要。为了有效检测网络犯罪,我们需要了解各种日志审计和入侵检测技术。下面将详细介绍UNIX和Linux平台的日志审计、防火墙日志及相关功能,以及商业入侵检测系统的特点。 UNIX和Linux平台的日志审计…

作者头像 李华
网站建设 2026/4/2 2:06:35

如何通过Kotaemon统一不同部门的术语体系?

如何通过Kotaemon统一不同部门的术语体系&#xff1f; 在大型企业中&#xff0c;一个看似简单的问题——“什么是‘资本化支出’&#xff1f;”——可能在财务部、研发部和法务部得到三种不同的解释。这种现象并不罕见&#xff1a;每个业务单元都发展出了自己的一套专业语言体系…

作者头像 李华
网站建设 2026/4/1 10:54:51

人力资源招聘助手:Kotaemon实现简历智能筛选

人力资源招聘助手&#xff1a;Kotaemon实现简历智能筛选 在企业招聘高峰期&#xff0c;HR每天面对成百上千份简历&#xff0c;手动筛选不仅耗时费力&#xff0c;还容易因主观判断导致优秀人才被遗漏。更棘手的是&#xff0c;岗位需求往往复杂多变——“三年以上Python后端经验”…

作者头像 李华
网站建设 2026/3/18 12:33:33

赛马娘Trainers‘ Legend G本地化插件完整使用手册

赛马娘Trainers Legend G本地化插件完整使用手册 【免费下载链接】Trainers-Legend-G 赛马娘本地化插件「Trainers Legend G」 项目地址: https://gitcode.com/gh_mirrors/tr/Trainers-Legend-G 还在为赛马娘游戏中的日文界面而困扰吗&#xff1f;Trainers Legend G本地…

作者头像 李华