当前位置: 首页 > news >正文

java:线程等待与唤醒 - Object的wait()和notify()

java:线程等待与唤醒 - Object的wait()和notify()

1 前言

java使用Object类的wait()和notify()方法,可以实现线程等待和唤醒(Object类为所有类的父类,即所有类天然具有线程等待和唤醒的方法,一般使用Object类的wait()和notify()方法即可)。

使用wait()、notify()时,有一些注意点,比如wait和notify方法需在同步代码块(synchronized 代码块)或方法(方法包含锁实例对象的synchronized实例方法,以及锁类对象的synchronized static方法)中使用,一般成对出现。

在一般执行时,还具有先后顺序的强依赖,即先执行wait,再执行notify,若先执行notify,再执行wait,后续无线程唤醒操作时,阻塞的线程将无法被唤醒。

2 使用

使用前,先关注下java文档中的说明:

* This method should only be called by a thread that is the owner
* of this object's monitor. A thread becomes the owner of the
* object's monitor in one of three ways:
* <ul>
* <li>By executing a synchronized instance method of that object.
* <li>By executing the body of a {@code synchronized} statement
*     that synchronizes on the object.
* <li>For objects of type {@code Class,} by executing a
*     synchronized static method of that class.
* </ul>* Only one thread at a time can own an object's monitor.
*
* @throws  IllegalMonitorStateException  if the current thread is not
*               the owner of this object's monitor.
* @see        java.lang.Object#notifyAll()
* @see        java.lang.Object#wait()
public final native void notify();* This method should only be called by a thread that is the owner
* of this object's monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
*
* @throws  IllegalMonitorStateException  if the current thread is not
*               the owner of the object's monitor.
* @throws  InterruptedException if any thread interrupted the
*             current thread before or while the current thread
*             was waiting for a notification.  The <i>interrupted
*             status</i> of the current thread is cleared when
*             this exception is thrown.
* @see        java.lang.Object#notify()
* @see        java.lang.Object#notifyAll()
*/
public final void wait() throws InterruptedException {wait(0);
}

上述表明,notify执行时,若当前线程不是Object的monitor的持有者,则抛出IllegalMonitorStateException。

判断是否当前线程持有Object的monitor,即上述提到的3个方式,要么在synchronized代码块中执行object.wait()或object.notify(),要么就是synchronized实例方法,此时synchronized锁对象为实例对象,若是synchronized static 方法,则synchronized锁对象为类对象,注意不同方式使用不同的锁对象即可,此3种方式表示当前线程为Object的monitor持有者,可以顺利执行wait()或notify()方法,反之则抛出IllegalMonitorStateException。

常见的使用方式如下:

public class TestObjectWaitAndNotify {private Object lockObj = new Object();private void doSubmit(){System.out.println("成功提交!");}public void run() throws Exception{AtomicBoolean f = new AtomicBoolean(false);new Thread(() -> {synchronized (this.lockObj){System.out.println(Thread.currentThread().getName() + "开始执行");while(!f.get()){try {this.lockObj.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() + "执行结束");doSubmit();}}, "xiaoxu1").start();TimeUnit.SECONDS.sleep(2);new Thread(() -> {synchronized (this.lockObj){System.out.println(Thread.currentThread().getName() + "开始执行");f.set(true);this.lockObj.notify();System.out.println(Thread.currentThread().getName() + "执行结束");}}, "xiaoxu2").start();}public static void main(String[] args) throws Exception{TestObjectWaitAndNotify n = new TestObjectWaitAndNotify();n.run();}
}

执行结果如下:

xiaoxu1开始执行
xiaoxu2开始执行
xiaoxu2执行结束
xiaoxu1执行结束
成功提交!

上述执行时,因为对象的监视器monitor含有该对象的锁、阻塞队列和同步队列,执行lockObj.wait()时,除了使当前线程进入阻塞队列,还需要释放锁(否则后续执行synchronized (this.lockObj)的第二个线程无法获取到锁并执行唤醒操作),然后后续休眠2秒后,第二个线程执行synchronized (this.lockObj),再次获取到锁(锁需是同一个对象的monitor持有的锁),执行唤醒操作,即阻塞队列中的休眠线程被再次唤醒并执行,执行后续的doSubmit(),且因为标志位改变,故而不再发起wait,整个过程结束。

另Object.notifyAll()方法,即唤醒当前阻塞队列的全部休眠线程(唤醒操作意即,notify、notifyAll会将阻塞队列中的线程,放入同步队列中等待执行,同时竞争锁失败的线程,也会放入同步队列中等待同步执行)。

注意,上述线程的等待和唤醒操作,因为加锁(synchronized决定了第一个线程会先于第二个线程获取到锁)和代码顺序,故而是先等待,再唤醒;若代码顺序为先唤醒,再等待,即便操作都加上synchronized(加上synchronized,保证了wait先执行,notify后执行),但因为代码操作顺序改变,阻塞队列没有休眠线程,此时再次执行wait,线程1将被一直阻塞无法唤醒。故wait()和notify()具有先后执行顺序的强依赖关系。

相关文章:

java:线程等待与唤醒 - Object的wait()和notify()

java&#xff1a;线程等待与唤醒 - Object的wait()和notify() 1 前言 java使用Object类的wait()和notify()方法&#xff0c;可以实现线程等待和唤醒&#xff08;Object类为所有类的父类&#xff0c;即所有类天然具有线程等待和唤醒的方法&#xff0c;一般使用Object类的wait(…...

实现弹窗功能并修改其中一个系数

把鼠标放在number-info上面,会是一个delon/chart的类库,可以在NG-ALAIN上找到阅读NG ALAIN的图表,以及number-info样式,数据文本 它拥有[title] [subtitle]两个可以是TemplateRef类型的,而template可以在里面放一些东西,比如按钮,所以可以放一个修改按钮 这里刚开始把template放…...

vue-draggable浏览器拖拽event事件对象拖动时 DragEvent path undefined

场景&#xff1a; 在做组件拖拽过程中&#xff0c;需要获取到触发元素冒泡过程中的所有元素&#xff0c;所以使用了event.path属性。在Chrome下正常运行&#xff0c;但是在FireFox下测试时发现&#xff0c;完犊子&#xff0c;失效了&#xff0c;通过问题排查&#xff0c;发现了…...

【云原生】搭建k8s高可用集群—20230225

文章目录多master&#xff08;高可用&#xff09;介绍高可用集群使用技术介绍搭建高可用k8s集群步骤1. 准备环境-系统初始化2. 在所有master节点上部署keepalived3.1 安装相关包3.2 配置master节点3.3 部署haproxy错误解决3. 所有节点安装Docker/kubeadm/kubelet4. 部署Kuberne…...

LeetCode121_121. 买卖股票的最佳时机

LeetCode121_121. 买卖股票的最佳时机 一、描述 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最…...

收割不易,五面Alibaba终拿Java岗offer

前言 前段时间有幸被阿里的一位同学内推&#xff0c;参加了阿里巴巴Java岗位的面试&#xff0c;本人19年双非本科软件工程专业&#xff0c;目前有一年半的工作经验&#xff0c;面试前就职于一家外包公司。如果在自己本人拿到offer之前&#xff0c;如果有人告诉我一年工作经验可…...

【离线数仓-4-数据仓库设计-分层规划构建流程】

离线数仓-4-数据仓库设计-分层规划&构建流程离线数仓-4-数据仓库设计-分层规划&构建流程1.数据仓库分层规划2.数据仓库构建流程1.数据调研1.业务调研2.需求分析3.总结2.明确数据域3.构建业务总线矩阵&维度模型设计4.明确统计指标1.指标体系相关概念1.原子指标2.派生…...

SQL零基础入门学习(十一)

SQL零基础入门学习&#xff08;十&#xff09; SQL NOT NULL 约束 NOT NULL 约束强制列不接受 NULL 值。 NOT NULL 约束强制字段始终包含值。这意味着&#xff0c;如果不向字段添加值&#xff0c;就无法插入新记录或者更新记录。 下面的 SQL 强制 “ID” 列、 “LastName” …...

排序基础之插入排序

目录 前言 一、什么是插入排序 二、实现插入排序 三、插入排序优化 四、插入排序的特性 前言 上一篇中我们说到了《排序基础之选择排序》&#xff0c;这一篇我们来学习一下排序算法中的另一种基础排序算法——插入排序。 一、什么是插入排序 简单来说就是&#xff1a;每…...

LabVIEW控制DO通道输出一个精确定时的数字波形

LabVIEW控制DO通道输出一个精确定时的数字波形如何使用数据采集板卡的DO通道输出一个精确定时的数字波形&#xff1f;解答:产生一个数字波形首先需要创建一个布尔数组&#xff0c;把波形序列信息放到该布尔数组中&#xff0c;然后通过一个布尔数组至数字转换vi来产生数字波形。…...

openpnp - 零碎记录

文章目录openpnp - 零碎记录概述笔记配置文件保存无效必须在查找问题之后, 才能保存配置文件如果想找出配置动作引起的配置内容变化, 还是要尝试保存后, 比对变化才行ENDopenpnp - 零碎记录 概述 这段时间, 正在配置校准手头的openpnp设备, 用的官网最新的openpnp2.0. 由于o…...

Qt编写微信支付宝支付

文章目录一 微信支付配置参数二 支付宝支付配置参数三 功能四 Demo效果图五 体验地址一 微信支付配置参数 微信支付API&#xff0c;需要三个基本必填参数。 微信公众号或者小程序等的appid&#xff1b;微信支付商户号mchId&#xff1b;微信支付商户密钥mchKey&#xff1b; 具…...

LeetCode 剑指 Offer 64. 求1+2+…+n

求 12…n &#xff0c;要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句&#xff08;A?B:C&#xff09;。 示例 1&#xff1a; 输入: n 3 输出: 6 限制&#xff1a; 1 < n < 10000 解法一&#xff1a;利用逻辑运算符的短路&#xf…...

Mapper代理开发

MyBatis快速开发https://blog.csdn.net/weixin_51882166/article/details/129204439?spm1001.2014.3001.5501 使用Mapper代理方式完成 定义与SQL映射文件同名的Mapper接口 &#xff0c;将Mapper接口和SQL映射文件放置同一目录结构 新建接口和包&#xff1a; 将Mapper接口和…...

为什么在连接mysql时,设置 SetConnMaxIdleTime 没有作用

目录测试1go 1.15.15go 1.17.12测试2go 1.15.15go 1.17.12参考在使用golang 连接 mysql时&#xff0c;为了节省连接资源&#xff0c;在连接使用过后&#xff0c;希望在指定长度时间不再使用后&#xff0c;自动关闭连接。 这时&#xff0c;经常会使用SetConnMaxLifetime()&#…...

嵌入式开发利器

前言 俗话说&#xff0c;工欲善其事必先利其器&#xff0c;做嵌入式开发首先需要选择好的工具&#xff0c;对的工具&#xff0c;工具选对了能事半功倍&#xff0c;节省很多时间&#xff0c;那些开发大佬一般都会使用各种各样的工具&#xff0c;不同的环节使用不同的工具&#…...

Qt 的QString类的使用

Qt的QString类提供了很方便的对字符串操作的接口。 使某个字符填满字符串&#xff0c;也就是说字符串里的所有字符都有等长度的ch来代替。 QString::fill ( QChar ch, int size -1 ) 例&#xff1a; QString str "Berlin";str.fill(z);// str "zzzzzz"…...

django项目部署(腾讯云服务器centos)

基本步骤&#xff1a; 购买腾讯云服务器并配配置好 >> 本地项目依赖收集准备 >> 上传项目等文件到服务器 >> 服务器安装部署软件和python环境 >> 开始部署&#xff08;全局来看就这5个步骤&#xff09; 目录 目录 1. 购买腾讯云服务器并配配置好 …...

计算机网络笔记、面试八股(一)——TCP/IP网络模型

Note&#xff1a;【计算机网络笔记、面试八股】系列文章共计5篇&#xff0c;现已更新3篇&#xff0c;剩余2篇&#xff08;TCP连接、Web响应&#xff09;会尽快更新&#xff0c;敬请期待&#xff01; 本章目录1. TCP/IP网络模型1.1 应用层1.1.1 应用层作用1.1.2 应用层有哪些常用…...

51单片机入门 - 简短的位运算实现扫描矩阵键盘

介绍 例程使用 SDCC 编译、 stcgal 烧录&#xff0c;如果你想要配置一样的环境&#xff0c;可以参考本专栏的第一篇文章“51单片机开发环境搭建 - VS Code 从编写到烧录”&#xff0c;我的设备是 Windows 10&#xff0c;使用普中51单片机开发板&#xff08;STC89C52RC&#xf…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...