Thread类的wait(),notify(),notifyAll()接口的使用方法实战后的理解

​ISP算法及架构分析介绍 ISP算法及架构分析介绍ISP即Image Signal Processor,是一种图像处理架构,不是我们用的下载器。ISP其实算是图像处理的一个特例,一般应用于前端设备(相对于SENSOR),从结果上看就是将RAW数据转换成压缩后的RGB(一般)数据,供后续CPU使用(识别、压缩等)。市面上很少有直接介绍ISP的书籍或者资料,今天我们主要是聊一聊ISP算法的架构,这样大... 阅读详情

java多线程在学习的时候感觉就那么几个类,几个方法,搞了一个生产者消费者例子就去参加校园招聘了。但真正用到后发现学的时候细节没有照顾到,有些问题也没有想过,所以书到用时方恨少。

既然生产者消费者这个例子是课堂上以及部分公司的招聘题目,那么就还是用它举个例子吧,例子不在于多么高大上,能帮助真正吸收就可以。

举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓 冲区中有内容待消费(不为空)。相应的,消费者可以通知生产者可以开始生成更多的数据,因为当它消耗掉某些数据后缓冲区不再为满。
 

所以在对一个方法,一个对象,或者一个消耗数据添加锁的时候,就要顾虑到是不是锁的同一个对象。如果.wait() 和 .notify()两个方法对应的对象或者消耗数据不是一个的话,就不抛出异常 java.lang.IllegalMonitorStateException

所以: java.lang.IllegalMonitorStateException 异常:

 

这个异常会在三种情况下抛出:
1>当前线程不含有当前对象的锁资源的时候,调用obj.wait()方法;
2>当前线程不含有当前对象的锁资源的时候,调用obj.notify()方法。
3>当前线程不含有当前对象的锁资源的时候,调用obj.notifyAll()方法。

那我们在避免出现上述异常的情况下,就需要对wait,notify方法的使用规则详细了解。

 

如何使用Wait

尽管关于wait和notify的概念很基础,它们也都是Object类的函数,但用它们来写代码却并不简单。

例如在错误的地方使用 synchronized 关键词,表现是不知道synchronized同步快怎么使用,同步那个对象呢。
没有用正确的对象调用wait,不知道对什么对象调用wait方法
或者没有遵循规范的代码方法。 关于wait方法是有一个规范的写法的
第一个问题就是,我们怎么在代码里使用wait()呢? 正确的方法是对在多线程间共享的那个Object来调用wait。在生产者消费者问题中,这 个共享的Object就是那个缓冲区队列。 
第二个问题是,既然我们应该在synchronized的函数或是对象里调用wait,那哪个对象应该被synchronized呢?答案是,那个 你希望上锁的对象就应该被synchronized,即那个在多个线程间被共享的对象。在生产者消费者问题中,应该被synchronized的就是那个 缓冲区队列。

现在你知道wait应该永远在被synchronized的同步块下和那个被多线程共享的对象上调用,下一个一定要记住的问题就是,你应该永远在 while循环,而不是if语句中调用wait。 
因为线程是在某些条件下等待的——在我们的例子里,即“如果缓冲区队列是满的话,那么生产者线程应该等 待”,你可能直觉就会写一个if语句。但if语句存在一些微妙的小问题,导致即使条件没被满足,你的线程你也有可能被错误地唤醒。所以如果你不在线程被唤 醒后再次使用while循环检查唤醒条件是否被满足,你的程序就有可能会出错——例如在缓冲区为满的时候生产者继续生成数据,或者缓冲区为空的时候消费者 开始消耗数据。所以记住,永远在while循环而不是if块中使用wait!

基于以上认知,下面这个是使用wait和notify函数的规范代码模板:


// The standard idiom for calling the wait method in Java
synchronized (sharedObject) {
while (condition) {
sharedObject.wait();
// (Releases lock, and reacquires on wakeup)
}
// do action based upon condition e.g. take or put into queue
}

在while循环里使用wait的目的,是在线程被唤醒的前后都持续检查条件是否被满足。生产者线程如果条件并未改变,那么这个线程并不能被唤醒,可以防止对缓冲区队列误操作。

这是用wait/notifyAll方法对一个列表操作的生产者和消费者模型。 
这个方法是对列表进行设置的方法。用一个生产者线程调用这个方法。
 

public void setValue() {
        try {
            synchronized (lock) {
                while (!ValueObject.value.equals("")) {
                    // 数据集不为空,那么生产者要休息
                    System.out.println("生产者 " + Thread.currentThread().getName() + " WAITING ***");
                    lock.wait();
                }
                System.out.println("生产者 " + Thread.currentThread().getName() + "RUNNABLE ");
                String value = System.currentTimeMillis() + "_" + System.nanoTime();
                ValueObject.value = value;
                lock.notifyAll();

            }
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

//这是一个获取列表数据的方法,由消费者线程调用。

public void getValue() {
        try {
            synchronized (lock) {
                while (ValueObject.value.equals("")) {
                    System.out.println("消费者" + Thread.currentThread().getName() + " WAITING**");
                    lock.wait();
                }
                System.out.println("消费者" + Thread.currentThread().getName() + " Runnable");
                ValueObject.value = "";
                lock.notifyAll();
            }
        } catch (Exception e) {
            // TODO: handle exception
        }

    }

本文重点: 
1. 你可以使用wait和notify函数来实现线程间通信。你可以用它们来实现多线程(>3)之间的通信。 
2. 永远在synchronized的函数或对象里使用wait、notify和notifyAll,不然Java虚拟机会生成 IllegalMonitorStateException。 
3. 永远在while循环里而不是if语句下使用wait。这样,会在线程暂停恢复后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知。 
4. 永远在多线程间共享的对象(在生产者消费者模型里即缓冲区队列)上使用wait。 
5. 基于前文提及的理由,更倾向用 notifyAll(),而不是 notify()。用notify()方法只是讲一个因为wait操作处于等待的线程唤醒。可能生产者只是唤醒生产者。而没有唤醒消费者。所以为了防止多线程下假死情况都是用notifyAll()方法
 

本文是根据个人实际开发工作中遇到的问题,结合网络搜索的资料整合而成,部分见解谨代表个人看法,如有问题,欢迎讨论。

参考文档:

代码示例参考博客

基于YOLO26/11/v8算法的Web目标检测系统,人脸表情识别系统,Django+Vue3 的前后端分离,实现摄像头实时识别,YOLO26/YOLO11/v8 + LLM大模型智能分析,科研必备 在人工智能迈向通用化(AGI)的今天,“视觉感知 + 语言理解”的多模态联合是未来的趋势。单纯的检测画框已经无法满足复杂的业务需求,如何让系统“看懂”画面并进行“思考”,是当前视觉项目的重点。我们知道目标检测是计算机视觉中的重要任务,广泛应用于安防监控、自动驾驶、智能家居等领域。因此本项目将 YOLO 目标检测模型(兼容 YOLO26/v11/v8 系列)与 DeepSeek 等顶流大语言模型(LLM) 进行联合,使用 Django (后端) + Vue3 (前端) 技术栈 阅读详情

相关推荐

【Codesys】-扫描添加失败,手动添加第三方模块,真·DC模式的高速计数模块

欧姆龙耦合器(NX-ECC201)和高速计数模块(NX-EC0132)单独使用。扫描设备添加到Codesys中,会报错,无法自动添加。记录一下,以防忘记。高速的计数保证了位置的准确性,位置准确就能保证裁切的精度,一切的基础就在这儿了,奈何目前只有欧姆龙和倍福能做到这样的波形。

qq_35316470的博客 1390

Java Thread.wait和Thread.notify方法

1. wait和notify方法 wait方法可以使当前执行代码的线程进行等待,notify方法用来通知哪些等待该对象锁的其它线程。wait和notify方法必须要获得该对象的锁,才能运行,否则会报IllegalMonitorStateException的异常。 try { Object lock = new Object(); synchronized (lock) { ...

假装你是大灰狼的专栏 3113

Win10网络图标消失,网络图标变成灰色,打开网络设置闪退等问题解决

介绍 主要解决如下问题 网络图标消失 常用方法配置中出现的网络图标变成灰色没有办法打开 打开网络和Internet闪退 错误提示`网络发现已关闭。网络计算机和设备不可见。请启动网络和共享中心的网络发现。 连不上网,诊断结果为 依赖服务或组无法启动 这个问题大概率通过重装系统不能解决,请大家谨慎测试之后最后选择重装这个路线。 方法1:这一步一定要做(卸载三方软件) 把360安全卫士,软件管家这些东西都卸载掉。 我的问题一开始就是这个软件引起的,可能他检测到我还给台式机配了无线网卡,然后就把有线网络的一些

呆呆象呆呆的博客 3万+

Java Thread.wait()

wait() 和 notify() 必须在 synchronized 语句块中使用 wait() 是强迫一个线程等待 notify() 是通知一个线程继续运行 更多精彩 更多技术博客,请移步 asing1elife’s blog 功能 wait() 是针对已经获取对象锁的线程进行操作 当线程获取对象锁后,调用 wait() 主动释放对象锁,同时该线程休眠 直到其他线程调用 notify(...

asing1elife's blog 1万+

Impala>Impala安装部署

文章目录1.安装前提2.下载安装包、依赖包3.虚拟机新增磁盘(可选)4.配置本地yum源5.安装Impala6.修改Hadoop、Hive配置7.修改impala配置8.启动、关闭impala服务 1.安装前提 集群提前安装好hadoop,hive。 hive安装包scp在所有需要安装impala的节点上,因为impala需要引用hive的依赖包。 hadoop框架需要支持C程序访问接口,查看下...

qq_44509920的博客 839

ENSP从下载到运行:用虚拟机搭建华为认证实验环境全流程(含USG6000V镜像配置)

本文提供了一份详细的华为ENSP仿真平台从下载、安装到配置USG6000V防火墙镜像的完整指南。内容涵盖前置软件安装、ENSP主程序配置、核心设备镜像导入及虚拟机资源分配策略,旨在帮助网络工程师和学习者快速搭建一个稳定、功能齐全的华为认证实验环境,为备考和模拟企业网络部署打下坚实基础。

weixin_29230865的博客 538

Java多线程学习之wait、notify/notifyAll 详解

1、wait()、notify/notifyAll() 方法是Object的本地final方法,无法被重写。 2、wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关键字使用,即,一般在synchronized 同步代码块里使用 wait()、notify/notifyAll() 方法。 3、 由于 wait()、notify/notifyAll() 在syn...

weixin_30827565的博客 728

Python 使用Pygame库实现足球游戏:创建一个球员和一个足球,并使玩家能够控制球员的移动。游戏将包括碰撞检测、简单的物理模拟,以及基本的用户输入处理

本文将介绍如何使用Python和Pygame库创建一个简单的足球游戏。我们将搭建一个基本的游戏环境,创建一个球员和一个足球,并使玩家能够控制球员的移动。游戏将包括碰撞检测、简单的物理模拟,以及基本的用户输入处理。这个简单的足球游戏展示了Pygame的一些基本功能。虽然这是一个简单的游戏,但它包含了创建游戏循环、用户输入处理、物理模拟、碰撞检测等重要概念。

程序熊的博客 744

Thread线程中wait()与notify()有何区别

一直对线程相关知识熟练使用但又感觉不是精深,现抽时间通过对线程的原理、基本使用、线程状态、线程中断、线程安全、线程池的详细梳理,整理成线程的系列博客文章,搭建成自己的一个线程知识体系,帮助自己更加全面深刻的认知和理解线程,希望对各位看官也能有帮助。

luo_boke的博客 1853

Android 13 Hotseat定制化修改——001 hotseat布局方向

一.背景由于需求是需要自定义修改Hotseat,所以此篇文章是记录如何自定义修改hotseat的,应该可以覆盖大部分场景,修改点有修改hotseat布局方向,hotseat图标数量,hotseat图标大小,hotseat布局位置,hotseat图标禁止形成文件夹,hotseat图标禁止移动到Launcher...

Java_fenxiang的博客 1104

手把手教你用TUSB2E22中继器实现eUSB2与USB 2.0互转(附实测数据对比)

本文详细介绍了如何利用TUSB2E22中继器实现eUSB2与USB 2.0的高效互转,包括技术背景、硬件设计要点、信号完整性测试方法及故障排查策略。通过实测数据对比,展示了TUSB2E22在信号延迟、功耗和眼图性能上的显著优势,为工程师提供了实用的工程方案。

weixin_29199873的博客 284

线程间通信

拥有相同锁的线程才可以实现wait/notify机制。它们都是Object类中的方法。wai使线程暂停运行,而notify通知暂停的线程继续运行。wait是使执行该方法的线程进行等待,在wait()所在的代码处暂停执行,并释放锁,直到接到通知或被中断为止。notify()也要在同步方法或同步块中调用,在调用前线程必须获得锁。执行notify()方法后,当前线程不会马上释放该锁,且等待状态的线程也并不能马上获取该对象锁。

KEEP CODING 216

STM32面试知识点总结分析

通过Boot引脚设定,寻找初始地址初始化栈指针 __initial_sp指向复位程序 Reset_Hander设置异常中断 HardFault_Handler设置系统时钟 SystemInit调用C库函数 _main。

嵌入式技术开发 2517

关于为什么线程通信的方法wait()、notify()、notifyAll()被定义在Object类里面?而sleep为什么定义在Thread类里面?

导语 在面试中经常会被问到多线程的知识,而在这个知识范围内,我们也会被问到关于wait、notify等这些方法。一般基础点的都会问使用的方法,当然这只是初级的问题,那么稍微深点的问题,可能就像我们标题这样:为什么线程通信的方法wait()、notify()、notifyAll()被定义在Object类里面?而sleep定义在Thread类里面? 其实这样的问题更多的是体现在程序实际上面,意思就...

寒山道杳 3769

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

被线程坑惨了!好好分析java线程中的wait、notify、notifyAll

在java中,线程间的通信可以使用wait、notify、notifyAll来进行控制。从名字就可以看出来这3个方法都是跟多线程相关的,但是可能让你感到吃惊的是:这3个方法并不是Thread类或者是Runnable接口的方法,而是Object类的3个本地方法。 下图是我总结的Java资料,想要资料的话请点795983544暗号优快云。 其实要理解这一点也并不难,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等.

banzhuanhu的博客 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java多线程:Thread的使用,以及wait(),notify(),notifyAll()

本文章是Java多线程系列的一篇文章,其他文章: Java多线程:锁的底层实现 Java多线程:synchronized和volatile Java多线程:JUC包-锁的封装 Java多线程:Thread的使用,以及wait(),notify(),notifyAll() Java多线程:线程池 一、Thread的状态 在Thread类的1750行左右定...

spawpaw的博客 1079

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

【Java笔记】wait()、notify() / notifyAll()、join() 和 sleep()

解读 wait()、notify() / notifyAll()、join() 和 sleep()

Origin_life的博客 801

深入理解Java多线程中的wait(),notify()和sleep()

大家在学习Java的过程中,势必要进行多线程的系统学习,这部分内容知识对于你在工作中的影响是极大的,并且在面试的过程中,这部分知识也是必然会被问到的。既然多线程的知识如此重要,那么我们就不能浅尝辄止。在这篇文章中,我想通过阅读源码的方式给大家分享一下我自己对于Java中wait(),notify()和sleep()的理解,并且在后面我也做一些内容上的扩展,与大家共同思考。如果在文章中有描述不妥或者

小游的博客 2万+

为什么wait/notify/notifyAll被定义在Object类中,而sleep定义在Thread类中,wait/notify和sleep方法的异同

为什么wait/notify/notifyAll被定义在Object类中,而sleep定义在Thread类中 因为java中每个对象都有一把称之为monitor监控器的锁 由于每个对象都可以上锁,这就要求在对象头中有一个用来保存锁信息的位置 这个锁是对象级别多大,而非线程级别的,wait/notify/notifyAll也都是锁级别的操作, 他们的锁属于对象 所以把他们定义在Object类中最合适,因为Objecct类是所有对象的父类 因为如果把wait/notify/notifyAll方法定义在Thre

4816

为什么 wait/notify/notifyAll 在 Object 类定义而不是 Thread 类?

作者:Yujiaao 来源:segmentfault.com/a/1190000019962661 一个较难回答的 Java 问题, Java 编程语言又不是你设计的,你如何回答这个问题呢?需要对 Java 编程的常识进行深入了解才行。 这个问题的好在它能反映面试者是否对 wait - notify 机制有没有了解, 以及他相关知识的理解是否明确。就像为什么 Java 中不支持多继承或者为什么 String 在 Java 中是final的问题一样,这个问题也可能有多个答案。 为什么在 Obj...

勇往直前的专栏 1784

通俗的深入解析notify()/notifyAll()和wait()方法

- notify()/notifyAll()和wait() notify()/notifyAll()唤醒单个/所有使用了wait()方法的线程,他们三个一般再synchronized锁住的代码块里面使用,所以说唤醒wait()的方法可不止一个哦~ ...

长臂人猿的博客 2108

JAVA进阶 THREAD学习08 wait()和notify()方法

个人感觉wait()和notify()方法的关系可以用“解铃还须系铃人”这句话来概括。当一个线程对一个对象使用方法,即这个线程在等待这个对象,可以看成;当这个对象使用了方法后,可以看成,被这个对象“系铃”的线程就被唤醒了。当然线程的,notify不能确定唤醒的线程,可以看成“系的铃”太多了,盲解一个应付。那么如果需要这个对象“系铃”的所有线程就可以使用notifyAll(),后,线程的运行不是按照顺序,而是需要的。

Roger_1900的博客 867

一个理解wait()与notify()的例子

下面是我原来在优快云论坛上看到的一个贴子,涉及到同步,wait(),notify()等概念的理解,我试着根据原来的一些回复和Think in Java上的相关概念将wait()和notify()这两个方法剖析了一下,欢迎指教.问题如下:file://分析这段程序,并解释一下,着重讲讲synchronized、wait(),notify 谢谢!class ThreadA {  public

xm4014的专栏 1万+

高级java每日一道面试题-2024年12月24日-并发篇-为什么wait, notify 和 notifyAll这些方法不在thread类里面 ?

总之,将wait()notify(), 和放在Object类中是为了支持 Java 的对象监视器机制,提供更细粒度、更灵活的线程同步能力。这样的设计不仅符合面向对象的原则,而且也为开发人员处理复杂的并发问题提供了强有力的工具。

qq_43071699的博客 954

为什么wait, notify,notifyAll保存在Object类中,而不是Thread类

多线程

ywl470812087的博客 1388

notify()、wait()、yield()方法的作用

notify和wait方法 wait和notify是属于Object的方法。 wait():导致当前线程等待,直到另一个线程调用该对象的notify()或者notifyAll()方法; notify():唤醒正在等待对象监视器的单个线程 notifyAll():唤醒全部正在等待对象监视器的单个线程 yield()方法 yield和sleep都输是属于Thread的方法。 yield()的作用是让步。让当前线程让出执行时间片。线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权

Session_s的博客 1660
上一篇: java 接口方法超时异常处理 设置超时时间
下一篇: 一次 java heap space 解决过程
coding_1994
博客等级 码龄9年 636粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值