重学java 43.多线程 多等待多唤醒案例

Fear never builds the future,but hope does.

                                                          —— 24.5.25

多等待多唤醒问题

        在多条线程同时消费同时等待时,会出现问题

BaoZiPu

package S77ThreadMoreWait;/*count和flag可以定义成包装类,但要记得给count和flag手动赋值不然对于本案例来说,容易出现空指针异常*/
public class BaoZiPu {// 包子的数目countprivate int count;// 是否有包子flagprivate boolean flag;public BaoZiPu() {}public BaoZiPu(int count, boolean flag) {this.count = count;this.flag = flag;}// getCount改成消费包子,直接输出包子数量countpublic void getCount() {System.out.println("消费了第"+count+"个包子");}// setCount改造成生产包子,count++public void setCount() {count++;System.out.println("生产了第"+count+"个包子");}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}
}

生产product线程

package S77ThreadMoreWait;// 实现Runnable接口
public class Product implements Runnable{BaoZiPu baoZiPu = new BaoZiPu();// 提供一个有参构造public Product(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {// 定义一个死循环while(true) {try {Thread.sleep(100L);}catch (InterruptedException e){throw new RuntimeException(e);}// 同步代码块synchronized (baoZiPu){// 1.判断flag是否为true,如果是true,证明有包子,生产线程等待if(baoZiPu.isFlag()==true){try{baoZiPu.wait();}catch(InterruptedException e){throw new RuntimeException(e);}}// 2.如果flag为false,证明没有包子,则要开始生产baoZiPu.setCount();// 3.改变flag为truebaoZiPu.setFlag(true);// 4.唤醒所有等待线程baoZiPu.notify();}}}
}

消费consumer线程

package S77ThreadMoreWait;public class Consumer implements Runnable{BaoZiPu baoZiPu = new BaoZiPu();// 提供一个有参构造public Consumer(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {while(true) {try {Thread.sleep(100L);}catch (InterruptedException e){throw new RuntimeException(e);}// 同步代码块synchronized (baoZiPu){// 1.判断flag是否为false,如果是false,证明没有包子,消费线程等待if(baoZiPu.isFlag()==false){// 抛出异常try{baoZiPu.wait();}catch(InterruptedException e){throw new RuntimeException(e);}}// 2.如果flag为true,则要开始消费baoZiPu.getCount();// 3.改变flag为false,消费完了,没有包子了baoZiPu.setFlag(false);// 4.唤醒所有等待线程baoZiPu.notify();}}}
}

测试类

package S77ThreadMoreWait;public class Demo216Test {public static void main(String[] args) {// 变成同一个对象BaoZiPu baoZiPu = new BaoZiPu();// 把baozipu对象分别传给两个线程中Product product = new Product(baoZiPu);Consumer consumer = new Consumer(baoZiPu);// 三条生产线程new Thread(product).start();new Thread(product).start();new Thread(product).start();// 三条消费线程new Thread(consumer).start();new Thread(consumer).start();new Thread(consumer).start();}
}

运行结果:会出现连续生产和连续消费的行为

         多条线程在同时等待时,上一条线程结束之后会随机唤醒一条线程,所以不能确定具体的顺序 

解决尝试 — 唤醒全部线程 notifyAll

   生产线程Product

package S77ThreadMoreWait;// 实现Runnable接口
public class Product implements Runnable{BaoZiPu baoZiPu = new BaoZiPu();// 提供一个有参构造public Product(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {// 定义一个死循环while(true) {try {Thread.sleep(100L);}catch (InterruptedException e){throw new RuntimeException(e);}// 同步代码块synchronized (baoZiPu){// 1.判断flag是否为true,如果是true,证明有包子,生产线程等待if(baoZiPu.isFlag()==true){try{baoZiPu.wait();}catch(InterruptedException e){throw new RuntimeException(e);}}// 2.如果flag为false,证明没有包子,则要开始生产baoZiPu.setCount();// 3.改变flag为truebaoZiPu.setFlag(true);// 4.唤醒所有等待线程baoZiPu.notifyAll();}}}
}

   消费线程Consumer

package S77ThreadMoreWait;public class Consumer implements Runnable{BaoZiPu baoZiPu = new BaoZiPu();// 提供一个有参构造public Consumer(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {while(true) {try {Thread.sleep(100L);}catch (InterruptedException e){throw new RuntimeException(e);}// 同步代码块synchronized (baoZiPu){// 1.判断flag是否为false,如果是false,证明没有包子,消费线程等待if(baoZiPu.isFlag()==false){// 抛出异常try{baoZiPu.wait();}catch(InterruptedException e){throw new RuntimeException(e);}}// 2.如果flag为true,则要开始消费baoZiPu.getCount();// 3.改变flag为false,消费完了,没有包子了baoZiPu.setFlag(false);// 4.唤醒所有等待线程baoZiPu.notifyAll();}}}
}

  运行结果:会出现连续生产和连续消费的行为

解决尝试 — 把 if 改成 while

 生产线程Product

package S77ThreadMoreWait;// 实现Runnable接口
public class Product implements Runnable{BaoZiPu baoZiPu = new BaoZiPu();// 提供一个有参构造public Product(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {// 定义一个死循环while(true) {try {Thread.sleep(100L);}catch (InterruptedException e){throw new RuntimeException(e);}// 同步代码块synchronized (baoZiPu){// 1.判断flag是否为true,如果是true,证明有包子,生产线程等待while (baoZiPu.isFlag()==true){try{baoZiPu.wait();}catch(InterruptedException e){throw new RuntimeException(e);}}// 2.如果flag为false,证明没有包子,则要开始生产baoZiPu.setCount();// 3.改变flag为truebaoZiPu.setFlag(true);// 4.唤醒所有等待线程baoZiPu.notifyAll();}}}
}

 消费线程Consumer

package S77ThreadMoreWait;public class Consumer implements Runnable{BaoZiPu baoZiPu = new BaoZiPu();// 提供一个有参构造public Consumer(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {while(true) {try {Thread.sleep(100L);}catch (InterruptedException e){throw new RuntimeException(e);}// 同步代码块synchronized (baoZiPu){// 1.判断flag是否为false,如果是false,证明没有包子,消费线程等待while (baoZiPu.isFlag()==false){// 抛出异常try{baoZiPu.wait();}catch(InterruptedException e){throw new RuntimeException(e);}}// 2.如果flag为true,则要开始消费baoZiPu.getCount();// 3.改变flag为false,消费完了,没有包子了baoZiPu.setFlag(false);// 4.唤醒所有等待线程baoZiPu.notifyAll();}}}
}

 运行结果:不会出现连续生产和连续消费的行为

总结:notifyAll和while要一起执行,才可以保证我们的代码不会出现错误情况

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

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

相关文章

python低阶基础100题(上册)

** python低阶基础100题(上册) ** 1. 请打印出字符串 Hello World print("Hello World")2. 请打印出字符串 爸爸妈妈,你们辛苦啦 print("爸爸妈妈,你们辛苦啦")3. 请打印出字符串 人生苦短,我…

SVN创建分支,分支合并,切换分支。通俗易懂

1、首先在svnbucket.com远程仓库上创建项目,这里我创建了个测试demo: 2、先把svn仓库的项目检出到自己的文件夹,我这里是demo001文件夹,此时并没有创建truck, branches, tags这三个目录: 3、 在demo001文件夹里新建tru…

vue实战 ---- 社交媒体---黑马头条项目

vue基础 1.介绍 为什么会有Vuex ? ​ Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 vuex是采用集中式管理组件依赖的共享数据的一个工具,可以解…

spring boot打的包直接运行

Spring Boot 提供了一个插件 spring-boot-maven-plugin 把程序打包成一个可执行的jar包&#xff0c;直接执行java -jar xxx.jar即可以启动程序 1、引用 spring-boot-maven-plugin插件 <build><plugins><plugin><groupId>org.springframework.boot<…

Hive安装教程

前置条件:hadoop&mysql docker容器安装mysql-CSDN博客 以下的/opt/bigdata目录根据自己实际情况更改 1.上传hive包并解压 tar -zxvf apache-hive-3.1.3-bin.tar.gz -C /opt/bigdata/ 2.修改路径 mv /opt/bigdata/apache-hive-3.1.3-bin/ hive cd /opt/bigdata/hive/…

全网最全网络基础思维导图合集(38张)

计算机网络基础知识点多且杂&#xff0c;想要系统地学习&#xff0c;思维导图肯定是必不可少的。 今天整理了38张思维导图&#xff0c;帮助你轻松理清思路&#xff0c;快速掌握关键内容。建议你收藏起来慢慢看&#xff0c;在看过之后最好能重新动手画一画&#xff0c;让计算机…

【数据结构】线性表习题 |顺序表 |链表 |栈和队列

&#x1f4d6;专栏文章&#xff1a;数据结构学习笔记 &#x1faaa;作者主页&#xff1a;格乐斯 前言 线性表习题 |顺序表 |链表 |栈和队列 顺序表和链表 1、 选B 1002(5-1)108* 第i个元素地址X&#xff0c;元素长度Len&#xff0c;第j个元素地址Y 公式&#xff1a;YXL…

Windows 7 SP1 安装VMtools -- 安装失败的解决方法

VMware安装Win7 SP1可以参考这篇文章&#xff1a;https://blog.csdn.net/2301_77225571/article/details/139121179?spm1001.2014.3001.5501 1.下载补丁 https://www.catalog.update.microsoft.com/search.aspx?qkb4474419 2.本机远控Win7 【Win】【R】&#xff0c;输入cmd…

第二十届文博会沙井艺立方分会场启幕!大咖齐打卡!

2024年5月24日-27日&#xff0c;第二十届中国&#xff08;深圳&#xff09;国际文化产业博览交易会沙井艺立方分会场活动将在艺立方非遗&#xff08;文旅&#xff09;产业园盛大举办。 本届文博会艺立方分会场活动办展特色鲜明&#xff0c;亮彩纷呈&#xff0c;将以“种下梧桐树…

aws eks理解和使用podidentity为pod授权

参考链接 https://www.amazonaws.cn/new/2024/amazon-eks-introduces-eks-pod-identity/https://aws.amazon.com/cn/blogs/aws/amazon-eks-pod-identity-simplifies-iam-permissions-for-applications-on-amazon-eks-clusters/ 先决条件 集群版本需要符合要求&#xff0c;如果…

【揭秘!在线ChatGPT神器,体验入口在此!】

&#x1f680;【揭秘&#xff01;在线ChatGPT神器&#xff0c;体验入口在此&#xff01;】&#x1f680; 前言 嘿&#xff0c;大家好&#xff01;今天我要和大家分享一些关于如何使用免费的ChatGPT的技巧。ChatGPT是一项令人兴奋的人工智能技术&#xff0c;它可以成为我们的好…

aws eks集成wasm运行时并启动pod

参考资料 WebAssembly 在云原生中的实践指南&#xff0c;https://cloud.tencent.com/developer/article/2324065 作为一种通用字节码技术&#xff0c;wasm的初衷是在浏览器中的程序实现原生应用性能。高级语言将wasm作为目标语言进行编译并运行在wasm解释器中。和nodejs类似的…

文件自动同步备份-FreeFileSync工具解决硬盘损坏、误操作覆盖导致数据丢失

文件自动同步备份-FreeFileSync工具解决硬盘损坏、误操作覆盖导致数据丢失 文章目录 文件自动同步备份-FreeFileSync工具解决硬盘损坏、误操作覆盖导致数据丢失前言一、FreeFileSync二、使用方法1.用外部存储卡或盘作为异地备份目标盘2.设置同步策略3.设置为windows的自动计划 …

将电脑D盘部分空间划分给C盘的方法

本文介绍在Windows电脑中&#xff0c;将D盘的部分空间分给C盘的方法。 最近&#xff0c;发现电脑中C盘的空间剩余不多了&#xff1b;而D盘由于当初分盘时划分的空间过多&#xff0c;导致其剩余空间很大且大概率以后都不会用上D盘中这些多余的空间了。因此&#xff0c;希望将D盘…

ubuntu20.04 安装系统后-开机黑屏-nvidia显卡驱动没问题_thinkpad-intel-13700H

文章目录 硬件现象原因&解决 硬件 thinkpad p1 gen6笔记本&#xff0c; intel 13代cpu 13700H,nvidia rtx 2000 Ada laptop gpu 13700H应该是有集显的&#xff0c;但可能没装集显驱动or由于Bios设置的缘故&#xff0c;我的win任务管理器只能看到一个gpu(gpu0)&#xff1…

学会这些大模型术语,你可以硬控朋友7.13分钟

你对于大型语言模型&#xff08;LLMs&#xff09;的复杂世界以及围绕它们的技术术语感到好奇吗&#xff1f; 理解从训练和微调的基础方面到转换器和强化学习的尖端概念&#xff0c;是揭开驱动现代人工智能大语言模型神秘面纱的第一步。 在本文中&#xff0c;我们将深入探讨 25 …

【软件设计师】大题

一、数据流图 基础知识 数据流图&#xff08;Data Flow Diagram,DFD&#xff09;基本图形元素&#xff1a; 外部实体&#xff08;External Agent&#xff09; 表示存在于系统之外的对象&#xff0c;用来帮助用户理解系统数据的来源和去向加工&#xff08;Process&#xff09;数…

网络安全基础技术扫盲篇 — 名词解释

网络模块基础&#xff08;网络拓扑图、网络设备、安全设备&#xff09; 用通俗易懂的话说&#xff1a; 网络拓扑图&#xff1a;它就像一张网络世界的地图&#xff0c;它展现了我们数不清的网站、服务器和设备是如何相互连接的。用简单的话说&#xff0c;它就是给我们指路、告…

基于移动多媒体信源与信道编码调研

前言 移动多媒体是指在移动通信环境下&#xff0c;通过无线网络传输的音频、视频、图像等多种媒体信息。移动多媒体的特点是数据量大、传输速率高、服务质量要求高&#xff0c;因此对信源编码和信道编码的性能提出了更高的要求。 本文对进3年的移动多媒体信源与信道编码的研究…

数美滑块研究

周一&#xff0c;在清晨的阳光照耀下&#xff0c;逆向山脚下的小镇宁静而安详。居民们忙碌地开始一天的生活&#xff0c;而在爬虫镇子的边缘&#xff0c;一座古朴的道观显得格外神秘。 阿羊正静静地坐在青石长凳上&#xff0c;摸鱼养神。突然&#xff0c;一道清脆的声音在他耳…