在Java多线程编程中,线程间的通信与协作是实现复杂并发逻辑的关键。wait()notify()以及sleep()方法作为线程控制的重要工具,有着各自独特的使用场景与规则。本文将深入探讨wait()notify()的协作机制,以及sleep()的阻塞特性,同时重点解析wait()必须在循环中调用的核心原因——防止虚假唤醒(Spurious Wakeup)。

一、wait/notify:线程间通信的桥梁

1.1 wait/notify的核心功能

wait()notify()是Object类的方法,主要用于线程间的协作与通信。

  • wait():当一个线程调用wait()方法时,它会释放当前持有的对象锁,并进入等待状态。直到其他线程调用同一个对象的notify()notifyAll()方法将其唤醒。
  • notify():随机唤醒一个在该对象上等待的线程;而notifyAll()则会唤醒所有在该对象上等待的线程。

关键操作时序图
线程通信时序图

1.2 wait/notify的使用规则

wait()notify()必须在synchronized同步代码块或同步方法中使用,这是因为它们的操作依赖于对象锁的状态。若不在同步环境中调用,会抛出IllegalMonitorStateException异常。

1.3 典型使用场景:生产者-消费者模型

class SharedResource {private int data;private boolean isEmpty = true;public synchronized void produce(int value) {while (!isEmpty) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}data = value;isEmpty = false;notifyAll();}public synchronized void consume() {while (isEmpty) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("Consumed: " + data);isEmpty = true;notifyAll();}
}

在上述代码中,生产者线程在缓冲区满时调用wait()等待,消费者线程消费数据后通过notifyAll()唤醒生产者;反之亦然。

二、sleep:简单的线程阻塞

2.1 sleep的特性

sleep()是Thread类的静态方法,用于让当前线程暂停执行指定的时间(以毫秒为单位)。与wait()不同,sleep()不会释放线程持有的锁。

2.2 使用场景

  • 模拟延迟:在测试代码或需要控制执行节奏的场景中,通过sleep()让线程暂停一段时间。
  • 避免过度占用资源:例如在轮询检查某个条件时,加入sleep()可以减少CPU的占用。
public class SleepExample {public static void main(String[] args) {Thread thread = new Thread(() -> {synchronized (SleepExample.class) {try {System.out.println("线程开始睡眠");Thread.sleep(2000);System.out.println("线程睡眠结束");} catch (InterruptedException e) {e.printStackTrace();}}});thread.start();}
}

在上述代码中,线程在持有锁的情况下进行睡眠,期间其他线程无法获取该锁。

三、为什么wait()必须在循环中调用:防止虚假唤醒

3.1 什么是虚假唤醒

虚假唤醒(Spurious Wakeup)是指线程在没有被其他线程调用notify()notifyAll()的情况下被唤醒。虽然这种情况在实际中并不常见,但Java的wait()机制允许它发生,这是JVM底层实现的结果。

3.2 循环检查的必要性

如果不使用循环,当发生虚假唤醒时,线程会误以为等待的条件已经满足,继续执行后续代码,可能导致程序逻辑错误。因此,wait()必须配合while循环使用,每次被唤醒后重新检查条件是否真正满足。

synchronized (obj) {while (!condition) {obj.wait();}// 条件满足,执行相应逻辑
}

通过while循环,即使发生虚假唤醒,线程也会重新进入等待状态,直到条件真正满足才继续执行。

四、总结

  • wait/notify:用于线程间的通信与协作,必须在同步环境中使用,且wait()要配合while循环防止虚假唤醒。
  • sleep:单纯的线程阻塞,不释放锁,适用于控制线程执行节奏。

理解这些方法的特性与使用规则,是编写正确、高效的多线程程序的基础。在实际开发中,合理运用这些工具,可以实现复杂的线程协作逻辑,同时避免因不当使用导致的各种问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/85010.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/85010.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/85010.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于使用EasyExcel、 Vue3实现导入导出功能

后端部分: 其中查询数据的服务省略 1、引用 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.3</version></dependency> 2、controller package com.rs.cphs.sys.controller;i…

机器学习中的数据准备关键技术

有效的数据准备对于构建强大的机器学习模型至关重要。本文档总结并阐述了为监督和非监督学习任务准备数据的关键技术。 1. 理解数据类型 有两种数据类型。定性数据描述对象的特征&#xff0c;而定量数据描述对象的数量。 定性&#xff08;分类&#xff09;数据 名义&#x…

深度学习——基于卷积神经网络实现食物图像分类【3】(保存最优模型)

文章目录 引言一、项目概述二、环境配置三、数据预处理3.1 数据转换设置3.2 数据集准备 四、自定义数据集类五、CNN模型架构六、训练与评估流程6.1 训练函数6.2 评估与模型保存 七、完整训练流程八、模型保存与加载8.1 保存模型8.2 加载模型 九、优化建议十、常见问题解决十一、…

《棒球百科》棒球怎么玩·棒球9号位

用最简单的方式介绍棒球的核心玩法和规则&#xff0c;完全零基础也能看懂&#xff1a; 一句话目标 进攻方&#xff1a;用球棒把球打飞&#xff0c;然后拼命跑完4个垒包&#xff08;逆时针绕一圈&#xff09;得分。 防守方&#xff1a;想尽办法让进攻方出局&#xff0c;阻止他…

语言模型是怎么工作的?通俗版原理解读!

大模型为什么能聊天、写代码、懂医学&#xff1f; 我们从四个关键模块&#xff0c;一步步拆开讲清楚 &#x1f447; ✅ 模块一&#xff1a;模型的“本事”从哪来&#xff1f;靠训练数据 别幻想它有意识&#xff0c;它的能力&#xff0c;全是“喂”出来的&#xff1a; 吃过成千…

nrf52811墨水屏edp_service.c文件学习

on_connect函数 /**brief Function for handling the ref BLE_GAP_EVT_CONNECTED event from the S110 SoftDevice.** param[in] p_epd EPD Service structure.* param[in] p_ble_evt Pointer to the event received from BLE stack.*/ static void on_connect(ble_epd_t …

Nginx-2 详解处理 Http 请求

Nginx-2 详解处理 Http 请求 Nginx 作为当今最流行的开源 Web 服务器之一&#xff0c;以其高性能、高稳定性和丰富的功能而闻名。在处理 HTTP请求 的过程中&#xff0c;Nginx 采用了模块化的设计&#xff0c;将整个请求处理流程划分为若干个阶段&#xff0c;每个阶段都可以由特…

40-Oracle 23 ai Bigfile~Smallfile-Basicfile~Securefile矩阵对比

小伙伴们是不是在文件选择上还默认给建文件4G/个么&#xff0c;在oracle每个版本上系统默认属性是什么&#xff0c;选择困难症了没&#xff0c;一起一次性文件存储和默认属性看透。 基于Oracle历代在存储架构的技术演进分析&#xff0c;结合版本升级和23ai新特性&#xff0c;一…

【一】零基础--分层强化学习概览

分层强化学习&#xff08;Hierarchical Reinforcement Learning, HRL&#xff09;最早一般视为1993 年封建强化学习的提出. 一、HL的基础理论 1.1 MDP MDP&#xff08;马尔可夫决策过程&#xff09;&#xff1a;MDP是一种用于建模序列决策问题的框架&#xff0c;包含状态&am…

Java延时

在 Java 中实现延时操作主要有以下几种方式&#xff0c;根据使用场景选择合适的方法&#xff1a; 1. Thread.sleep()&#xff08;最常用&#xff09; java 复制 下载 try {// 延时 1000 毫秒&#xff08;1秒&#xff09;Thread.sleep(1000); } catch (InterruptedExcepti…

电阻篇---下拉电阻的取值

下拉电阻的取值需要综合考虑电路驱动能力、功耗、信号完整性、噪声容限等多方面因素。以下是详细的取值分析及方法&#xff1a; 一、下拉电阻的核心影响因素 1. 驱动能力与电流限制 单片机 IO 口驱动能力&#xff1a;如 STM32 的 IO 口在输入模式下的漏电流通常很小&#xf…

NY271NY274美光科技固态NY278NY284

美光科技NY系列固态硬盘深度剖析&#xff1a;技术、市场与未来 技术前沿&#xff1a;232层NAND架构与性能突破 在存储技术的赛道上&#xff0c;美光科技&#xff08;Micron&#xff09;始终是行业领跑者。其NY系列固态硬盘&#xff08;SSD&#xff09;凭借232层NAND闪存架构的…

微信开发者工具 插件未授权使用,user uni can not visit app

参考&#xff1a;https://www.jingpinma.cn/archives/159.html 问题描述 我下载了一个别人的小程序&#xff0c;想运行看看效果&#xff0c;结果报错信息如下 原因 其实就是插件没有安装&#xff0c;需要到小程序平台安装插件。处理办法如下 在 app.json 里&#xff0c;声…

UE5 读取配置文件

使用免费的Varest插件&#xff0c;可以读取本地的json数据 获取配置文件路径&#xff1a;当前配置文件在工程根目录&#xff0c;打包后在 Windows/项目名称 下 读取json 打包后需要手动复制配置文件到Windows/项目名称 下

【kdump专栏】KEXEC机制中SME(安全内存加密)

【kdump专栏】KEXEC机制中SME&#xff08;安全内存加密&#xff09; 原始代码&#xff1a; /* Ensure that these pages are decrypted if SME is enabled. */ 533 if (pages) 534 arch_kexec_post_alloc_pages(page_address(pages), 1 << order, 0);&#x1f4cc…

C# vs2022 找不到指定的 SDK“Microsof.NET.Sdk

找不到指定的 SDK"Microsof.NET.Sdk 第一查 看 系统盘目录 C:\Program Files\dotnet第二 命令行输入 dotnet --version第三 检查环境变量总结 只要执行dotnet --version 正常返回版本号此问题即解决 第一查 看 系统盘目录 C:\Program Files\dotnet 有2种方式 去检查 是否…

Pytest断言全解析:掌握测试验证的核心艺术

Pytest断言全解析&#xff1a;掌握测试验证的核心艺术 一、断言的本质与重要性 什么是断言&#xff1f; 断言是自动化测试中的验证检查点&#xff0c;用于确认代码行为是否符合预期。在Pytest中&#xff0c;断言直接使用Python原生assert语句&#xff0c;当条件不满足时抛出…

【编译原理】题目合集(一)

未经许可,禁止转载。 文章目录 选择填空综合选择 将编译程序分成若干个“遍”是为了 (D.利用有限的机器内存,但降低了执行效率) A.提高程序的执行效率 B.使程序的结构更加清晰 C.利用有限的机器内存并提高执行效率 D.利用有限的机器内存,但降低了执行效率 词法分析…

uni-app项目实战笔记13--全屏页面的absolute定位布局和fit-content自适应内容宽度

本篇主要实现全屏页面的布局&#xff0c;其中还涉及内容自适应宽度。 创建一个preview.vue页面用于图片预览&#xff0c;写入以下代码&#xff1a; <template><view class"preview"><swiper circular><swiper-item v-for"item in 5&quo…

OVS Faucet Tutorial笔记(下)

官方文档&#xff1a; OVS Faucet Tutorial 5、Routing Faucet Router 通过控制器模拟三层网关&#xff0c;提供 ARP 应答、路由转发功能。 5.1 控制器配置 5.1.1 编辑控制器yaml文件&#xff0c;增加router配置 rootserver1:~/faucet/inst# vi faucet.yaml dps:switch-1:d…