Java 中Object的wait() notify() notifyAll()方法使用

发布时间 - 2026-01-11 01:24:29    点击率:

Java 中Object的wait() notify() notifyAll()方法使用

一、前言

  对于并发编程而言,除了Thread以外,对Object对象的wati和notify对象也应该深入了解其用法,虽然知识点不多。

二、线程安全基本知识

  首先应该记住以下基本点,先背下来也无妨:

同一时间一个锁只能被一个线程持有 调用对象的wait()和notify()前必须持有它

三、wait()和notify()理解

3.1 wait()和notify()方法简介

  wait()和notify()都是Object的方法,可以认为任意一个Object都是一种资源(或者资源的一个代表),当多个线程对一个资源进行操作时,如果线程发现这个资源还没有准备好,它就可以在这个资源上进行等待,即调用这个资源的wait()方法,如果有另外的线程经过某些处理觉得这个资源可用了,会调用这个这个资源的notify()方法,告诉等待它的线程,这个资源可以用了。

  当然不使用wait()和notify()方法也是可以的,可以用while()死循环来判断,如下面的伪代码:

class Resource{
  static boolean canUse=false;
}

while(!Resource.canUse){
  //如果不可用,死循环在这里等待
}

//当资源可以使用后,就会跳出循环,往下执行

  这样做是可以,但是特别消耗CPU资源,所以建议用户使用wait()和notify()方法。

3.2 wait()和notify()的价值

  其实从单词意思来看就能看出来,wait就是等待,说明这个资源没有准备好,我要等,还有这一个wait(long timeout) ,表示我只能等待你这么长时间了,过时不候啊,而调用notify()的线程肯定就是对资源进行处理的,处理完进行通知。所以呢,它们就经常用在生产者和消费者模式中。任何涉及等资源到来的情景都适合用这两个方法,

3.3 为什么wait()和notify()必须和synchronized一起使用

  当不在synchronized同步块中使用wait()和notify()或者调用方法的对象不是synchronized的同步锁就会抛异常:

java.lang.IllegalMonitorStateException

  很多人会疑惑为什么必须持有这个对象的锁才能调用对象的wait()和notify()方法呢,我也有这个疑惑,而且我认为这么做是没有必要的。首先看下面的代码:

public class WaitTest{
  // 这是一个资源,模拟的Object
  final NoObjct resource=new NoObjct();
  public static void main(String[] args) throws Exception{
    WaitTest d=new WaitTest();
    d.test();
  }

  public void test() throws Exception{
    Runnable r=new Runnable(){
      public void run(){
        // 调用资源的模拟的wait方法,在方法内部使用synchronized
        resource.noWait();
        System.out.println('线程等待完,执行');
      }
    };
    Thread t=new Thread(r);
    t.start();
    Thread.sleep(2000);
    System.out.println('准备唤醒等待资源的线程');
    // 调用资源的模拟的notify方法,在方法内部使用synchronized
    resource.noNotify();
  }
}

// 因wait()和notify()是final方法,不能覆盖,所以模拟一个Object对象
class NoObjct{
  // 模拟wait方法
  public void noWait(){
    // 这个就相当于将synchronized放到wait方法内部
    synchronized(this){
      try{
        this.wait();
      }catch(InterruptedException e){
        e.printStackTrace();
      }
    }
  }
  // 模拟notify方法
  public void noNotify(){
    // 这个就相当于将synchronized放到notify方法内部
    synchronized(this){
      this.notify();
    }
  }
}

  这是一个简单的wait()和notify()例子,wait等待,notify唤醒。如果忽略掉模拟的Object会发现代码简洁了许多,否则就要每次使用synchronized,如下代码:

public class WaitTest{
  // 这是一个资源,模拟的Object
  final Object resource=new Object();

  public static void main(String[] args) throws Exception{
    WaitTest d=new WaitTest();
    d.test();
  }

  public void test() throws Exception{
    Runnable r=new Runnable(){
      public void run(){
        // 必须使用synchronized
        try{
          synchronized(resource){
            resource.wait();
          }
        }catch(InterruptedException e){
          e.printStackTrace();
        }
        System.out.println('线程等待完,执行');
      }
    };
    Thread t=new Thread(r);
    t.start();

    Thread.sleep(2000);
    System.out.println('准备唤醒等待资源的线程');
    // 必须使用synchronized
    synchronized(resource){
      resource.notify();
    }
  }
}

  所以呢,我觉得wait()和notify()和synchronized一起没有什么意义,毕竟synchronized用来进行代码同步的,和线程之间唤醒没有什么关系(希望有读者能给我相反的意见并说服我)。但是既然这么规定了就必须要去遵守,即必须在synchronized中使用wait和notify,且调用方法的对象必须是同步对象。

四、何时使用wait()和notify()

  在上面已经说了这两个方法的其中一个价值就是用在生产者和消费者模式。但是通过使用它们来构建的生产者和消费者模型很低级而且复杂,完全可以使用BlockingQueue接口的实现类来构建。比如可以使用ArrayBlockingQueue,它既能保证线程安全又能实现阻塞效果,何乐而不为呢。

  除此之外就只有线程间休眠与唤醒了。

     感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


# Java  # 中Object的wait()  # notify()  # notifyAll()  # Object  # 中wait()详解  # java多线程之wait()  # notifyAll()的详解分析  # Java的wait()  # notify()和notifyAll()使用心得  # Java使用wait() notify()方法操作共享资源详解  # Java多线程通信wait()和notify()代码实例  # java wait()/notify() 实现生产者消费者模式详解  # Java多线程wait()和notify()方法详细图解  # java使用wait()和notify()线程间通讯的实现  # JAVA中wait()和notify()如何使用详解  # 这是一个  # 可以使用  # 都是  # 就会  # 没有什么  # 这两个  # 用了  # 用在  # 这一  # 我要  # 给我  # 在这里  # 还没有  # 也有  # 在这个  # 我觉得  # 多个  # 说了  # 可以用  # 不多 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Java Adapter 适配器模式(类适配器,对象适配器)优缺点对比  如何快速辨别茅台真假?关键步骤解析  高防服务器:AI智能防御DDoS攻击与数据安全保障  Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程  ChatGPT 4.0官网入口地址 ChatGPT在线体验官网  制作旅游网站html,怎样注册旅游网站?  Laravel API资源类怎么用_Laravel API Resource数据转换  如何用wdcp快速搭建高效网站?  Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置  php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】  专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?  Laravel如何使用Telescope进行调试?(安装和使用教程)  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  ,在苏州找工作,上哪个网站比较好?  Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知  如何在IIS中新建站点并配置端口与IP地址?  大同网页,大同瑞慈医院官网?  如何在HTML表单中获取用户输入并用JavaScript动态控制复利计算循环  Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】  laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程  Laravel如何创建自定义Facades?(详细步骤)  EditPlus中的正则表达式 实战(4)  三星、SK海力士获美批准:可向中国出口芯片制造设备  如何在局域网内绑定自建网站域名?  成都网站制作公司哪家好,四川省职工服务网是做什么用?  如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)  浅述节点的创建及常见功能的实现  ,怎么在广州志愿者网站注册?  jQuery 常见小例汇总  网站制作软件有哪些,制图软件有哪些?  高防服务器租用指南:配置选择与快速部署攻略  Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】  黑客如何通过漏洞一步步攻陷网站服务器?  合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?  网站制作免费,什么网站能看正片电影?  EditPlus中的正则表达式实战(6)  佛山网站制作系统,佛山企业变更地址网上办理步骤?  iOS正则表达式验证手机号、邮箱、身份证号等  php json中文编码为null的解决办法  Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】  Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践  详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)  Laravel Livewire是什么_使用Laravel Livewire构建动态前端界面  香港服务器选型指南:免备案配置与高效建站方案解析  企业网站制作这些问题要关注  Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】  Android 常见的图片加载框架详细介绍  Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)  如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】  长沙企业网站制作哪家好,长沙水业集团官方网站?