【线程】wait()+notifyAll()实现多个线程交替遍历,输出ABCABC
背景
有三个线程,每个线程分别循环输出A、B、C,各线程循环10次,要求输出结果是ABCABCABC这样的
代码
@Data
public class PrintThread extends Thread {private String string; // 输出的字符串private int order; // 输出的顺序private static Object lock; // 静态锁对象private static volatile int index = 0; // 共享的索引变量public PrintThread(String string, int order, Object lock) {this.string = string;this.order = order;this.lock = lock;}@Overridepublic void run() {for (int i = 0; i < 10; i++) {synchronized (lock) { // 使用锁对象进行同步while (index % 3 != order) { // 判断是否轮到当前线程输出try {lock.wait(); // 如果不是轮到当前线程输出,则释放锁并等待} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(10); // 模拟输出过程的耗时操作} catch (InterruptedException e) {e.printStackTrace();}index++; // 修改索引变量,表示下一个线程可以输出了System.out.println(string); // 输出字符串lock.notifyAll(); // 唤醒其他等待的线程}}}public static void main(String[] args) {try {Object lock = new Object(); // 创建锁对象PrintThread threadA = new PrintThread("A", 0, lock); // 创建线程APrintThread threadB = new PrintThread("B", 1, lock); // 创建线程BPrintThread threadC = new PrintThread("C", 2, lock); // 创建线程CthreadA.start(); // 启动线程AthreadB.start(); // 启动线程BthreadC.start(); // 启动线程C} catch (Exception e) {e.printStackTrace();}}
}
最后
实际会有这样的场景吗?下面举几个例子
1、假设在一个食堂,有很多人在排队打饭,每个人需要完成以下步骤:先拿餐具,然后拿菜,再拿饭,最后付钱。
2、多线程下载器。当我们下载一个大文件时,可以使用多个线程同时从不同的服务器上下载文件的不同部分,然后将这些部分合并成一个完整的文件。通过多个线程交替遍历不同的服务器,可以提高下载速度,加快文件的下载过程。
3、医院的门诊、机场的登机口、超市的收银台等等。
扩展
除了wait+notifyAll,还有其他的实现方式
-
使用
CountDownLatch:CountDownLatch是一个同步辅助类,可以用于控制一个或多个线程等待其他线程完成操作。它通过一个计数器来实现,线程调用await()方法等待计数器变为0,而其他线程调用countDown()方法来减少计数器的值。当计数器变为0时,等待的线程将被唤醒。 -
使用
CyclicBarrier:CyclicBarrier也是一个同步辅助类,可以用于多个线程之间的同步。它和CountDownLatch类似,都是通过计数器来实现线程的等待和唤醒。不同之处在于,CyclicBarrier的计数器可以重复使用,当计数器减为0时,所有等待的线程都会被唤醒,并且计数器会被重置为初始值。 -
使用
Semaphore:Semaphore是一个计数信号量,可以用来控制同时访问某个资源的线程个数。它维护了一个许可证的计数器,线程可以通过acquire()方法获取许可证,如果计数器大于0,线程可以继续执行;如果计数器为0,线程将被阻塞。线程在使用完资源后,需要调用release()方法释放许可证,使得其他线程可以继续访问资源。 -
使用
Lock和Condition:Lock是一个可重入的互斥锁,可以用来替代synchronized关键字实现线程的同步。Condition是与Lock相关联的条件对象,可以用来实现线程的等待和唤醒。线程可以通过调用await()方法等待条件满足,而其他线程可以通过调用signal()或signalAll()方法来唤醒等待的线程。
相关文章:
【线程】wait()+notifyAll()实现多个线程交替遍历,输出ABCABC
背景 有三个线程,每个线程分别循环输出A、B、C,各线程循环10次,要求输出结果是ABCABCABC这样的 代码 Data public class PrintThread extends Thread {private String string; // 输出的字符串private int order; …...
MyBatis 缓存机制复习及项目中的应用经历
背景 想起前两年工作中因为二级缓存默认开启导致的问题,完整的看了一个介绍 MyBatis 缓存机制的视频《MyBatis 缓存基础知识讲解》。 总计知识点: 缓存的类型及开关这是个形同虚设的功能,线上环境应该禁用缓存 MyBatis 缓存分类 MyBasit…...
匈牙利算法详解
匈牙利算法(Hungarian Algorithm)是一种组合优化算法(combinatorial optimization algorithm),用于求解指派问题(assignment problem),算法时间复杂度为O(N^3)。Harold Kuhn发表于1955年,由于该算法基于两位匈牙利数学家的早期研究成果&#…...
script的三种加载模式
默认加载:阻断dom树构建(html文档解析),下载资源,然后立即执行,完毕后再进行dom树构建defer 加载:下载照旧,但执行延后。即下载资源和dom构建同时进行,但等dom树构建完再执行async:下…...
mongo 中两张表联合查询
表1:user 表 表2:dept表 需要查询user表中roleCodes 包含shr 的数据 然后联合dept表 需要部门名称 db.user.aggregate([{$match: {roleCodes: "shr" // 匹配roleCodes包含"shr"的文档}},{$lookup: {from: "dept", // 关联的集合名称loc…...
【Linux】多路转接 -- epoll
文章目录 1. 认识epoll2. epoll相关系统调用接口3. epoll工作原理4. epoll服务器5. epoll的优点6. epoll的工作方式7. epoll的使用场景 1. 认识epoll epoll系统调用和select以及poll是一样的,都是可以让我们的程序同时监视多个文件描述符上的事件是否就绪。 epoll…...
学会RabbitMQ的延迟队列,提高消息处理效率
系列文章目录 手把手教你,本地RabbitMQ服务搭建(windows) 消息队列选型——为什么选择RabbitMQ RabbitMQ灵活运用,怎么理解五种消息模型 RabbitMQ 能保证消息可靠性吗 推或拉? RabbitMQ 消费模式该如何选择 死信是什么…...
ChatGPT会取代搜索引擎吗?BingChat、GoogleBard与ChatGPT区别
目前暂时不会,ChatGPT为代表的聊天机器人很可能会直接集成到搜索中,而不是取代它。微软已经通过Bing Chat和Bing做到了这一点,它将“聊天”选项卡直接放入Bing搜索的菜单中。Google、百度也分别开始尝试通过其AI生成技术将Google Bard、文心一…...
多个QLabel中文字左右对其问题研究
众所周知,关于QLabel 中的文字对其方式,官方提供多种,具体可参考 AlignmentFlag,这里就不详细列举了。 实际开发中有这样一个需求:多个lab中,文字显示不同,长度不一,但想要实现视觉…...
链式二叉树统计结点个数的方法和bug
方法一: 分治:分而治之 int BTreeSize1(BTNode* root) {if (root NULL) return 0;else return BTreeSize(root->left)BTreeSize(root->right)1; } 方法二: 遍历计数:设置一个计数器,对二叉树正常访问&#…...
C语言-报错集锦-03-malloc(): memory corruption: 0x0000000001496d90 ***
一、报错信息 [2023-8]--[ Debug ]--Push Data To StAccessPath OK. [2023-8]--[ Debug ]--Judge Vertex(0) Is Not Accessed. [2023-8]--[ Debug ]--Judge Vertex(2) Is Accessed. [2023-8]--[ Debug ]--Judge Vertex(3) Is Not Accessed. [2023-8]--[ Debug ]--Judge Vertex…...
现代C++中的从头开始深度学习:【5/8】卷积
一、说明 在上一个故事中,我们介绍了机器学习的一些最相关的编码方面,例如 functional 规划、矢量化和线性代数规划。 现在,让我们通过使用 2D 卷积实现实际编码深度学习模型来开始我们的道路。让我们开始吧。 二、关于本系列 我们将学习如何…...
以太网帧格式与吞吐量计算
以太网帧结构 帧大小的定义 以太网单个最大帧 6(目的MAC地址) 6(源MAC地址) 2(帧类型) 1500{IP数据包[IP头(20)DATA(1480)]} 4(CRC校验ÿ…...
vue中install方法
1:语法 vue提供install可供我们开发新的插件及全局注册组件等 install方法第一个参数是vue的构造器,第二个参数是可选的选项对象 export default {install(Vue,option){组件指令混入挂载vue原型} }2:注册组件 一:注册单个组件 1…...
Flutter:文件读取—— video_player、chewie、image_picker、file_picker
前言 简单学习一下几个比较好用的文件读取库 video_player 简介 用于视频播放 官方文档 https://pub-web.flutter-io.cn/packages/video_player 安装 flutter pub add video_player加载网络视频 class _MyHomePageState extends State<MyHomePage> {// 控制器late…...
vim的使用
vim文本编辑器 vim介绍命令模式光标移动选中内容复制内容粘贴内容删除撤销/恢复字符转换 编辑模式末行模式保存/退出查找行号显示文件切换 扩展 vim介绍 vim是Linux自带的文本编辑器,具有命令模式、编辑模式、末行模式三种模式。 模式间的切换: 命令模…...
马氏杆法检查斜视
使用 检查水平向斜视时,使用水平向马氏杆检查;重直向斜视时,使用重直问马氏杆;检查旋转斜视时,使用双马氏杆. 检查水平向斜视 双眼屈光不正全矫 双眼同时打开,右眼前加水平向马氏杆,左眼前不加 双眼同时观察点光源&…...
Mac电脑怎么使用“磁盘工具”修复磁盘
我们可以使用“磁盘工具”的“急救”功能来查找和修复磁盘错误。 “磁盘工具”可以查找和修复与 Mac 磁盘的格式及目录结构有关的错误。使用 Mac 时,错误可能会导致意外行为,而重大错误甚至可能会导致 Mac 彻底无法启动。 继续之前,请确保您…...
c++画出分割图像,水平线和垂直线
1、pca 找到图像某个区域的垂直线,并画出来 // 1、 斑块的框 血管二值化图,pca 找到垂直血管壁的直线, 还是根据斑块找主轴方向吧// Step 1: 提取斑块左右范围内的血管像素点坐标,std::vector<cv::Point> points;for (int y 0; y <…...
Python 程序设计入门(015)—— enumerate() 函数的用法
Python 程序设计入门(015)—— enumerate() 函数的用法 目录 Python 程序设计入门(015)—— enumerate() 函数的用法一、enumerate() 函数的语法二、为可迭代对象创建索引三、将字符串、列表等转换为字典1、将字符串转换为字典2、…...
解放词库自由:跨平台词库迁移的全场景解决方案
解放词库自由:跨平台词库迁移的全场景解决方案 【免费下载链接】imewlconverter ”深蓝词库转换“ 一款开源免费的输入法词库转换程序 项目地址: https://gitcode.com/gh_mirrors/im/imewlconverter 当你更换新手机时,是否曾为输入法里积累多年的…...
Qwen3.5-4B模型在VS Code中的集成:打造个人AI编程工作站
Qwen3.5-4B模型在VS Code中的集成:打造个人AI编程工作站 1. 前言:为什么要在VS Code中集成Qwen3.5-4B 作为一名开发者,你可能已经习惯了在各种在线平台上使用AI辅助编程。但有没有想过,把这些能力直接搬到你的本地开发环境中&am…...
手把手教你用NVIDIA TX2串口控制大疆C620电机(USB转CAN模块保姆级教程)
从零实现NVIDIA TX2通过USB-CAN模块精准控制大疆C620电机 硬件连接与基础原理 当我们需要在机器人项目中实现高精度电机控制时,CAN总线通信往往是首选方案。但对于使用NVIDIA Jetson TX2这类开发板的新手来说,可能会遇到两个现实问题:TX2原生…...
OpenClaw学术助手:Qwen2.5-VL-7B论文图表解析与总结
OpenClaw学术助手:Qwen2.5-VL-7B论文图表解析与总结 1. 为什么需要学术文献自动化处理 作为一名经常需要阅读大量文献的研究人员,我深刻体会到手动处理论文的痛点。每次下载几十篇PDF,光是浏览摘要筛选出相关文献就要耗费半天时间。更不用说…...
学术PDF处理神器:OpenClaw+千问3.5-35B-A3B-FP8实现论文公式截图转LaTeX
学术PDF处理神器:OpenClaw千问3.5-35B-A3B-FP8实现论文公式截图转LaTeX 1. 为什么需要自动化论文公式处理 作为经常与学术论文打交道的科研人员,我深刻理解手动输入LaTeX公式的痛苦。去年撰写博士论文期间,我曾花费整整两周时间仅用于转录参…...
ns-3.43环境搭建避坑实录:从依赖冲突到‘first.cc’成功运行的完整排错指南
ns-3.43环境搭建避坑实录:从依赖冲突到first.cc成功运行的完整排错指南 当你在Ubuntu 24.04上第一次尝试搭建ns-3.43网络模拟环境时,可能会遇到各种意想不到的问题。这篇文章不是又一份按部就班的安装指南,而是一份真实的问题解决手册&#x…...
滨会生物冲刺港股:年亏1.2亿 乐普生物与扬子江药业是股东
雷递网 雷建平 4月5日武汉滨会生物科技股份有限公司(简称:“滨会生物”)日前更新招股书,准备在港交所上市。滨会生物总计募资超10亿元,其中,2021年2月完成募资6亿元,2022年7月完成募资2.4亿元&a…...
UE5地牢生成实战:从零搭建程序化地下城(附完整蓝图逻辑)
UE5地牢生成实战:从零搭建程序化地下城(附完整蓝图逻辑) 在游戏开发中,程序化内容生成(PCG)技术正变得越来越重要。想象一下,你正在开发一款Roguelike游戏,每次玩家进入地牢都能获得全新的探索体验——这正…...
03_Neo4j知识体系之5.x与2026.x新特性和版本演进
03_Neo4j知识体系之5.x与2026.x新特性和版本演进 体系 版本演进层:Neo4j 5.x LTS、2025/2026 日历化版本、Cypher 5 与 Cypher 25、Autonomous Clustering、Ops Manager、Vector Indexes、AI 能力关联能力:与升级迁移路径、集群扩容、Fabric 联邦查询、差…...
IGBT驱动电路设计避坑指南:从选型到PCB布局的8个关键点
IGBT驱动电路设计避坑指南:从选型到PCB布局的8个关键点 在电力电子领域,IGBT驱动电路的设计质量直接决定了整个系统的可靠性和效率。我曾亲眼见过一个价值百万的变频器项目,因为驱动电阻选型不当导致批量烧毁,团队不得不连续加班三…...
