重学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/…

若依框架代码生成器详解:从入门到高级定制

若依框架&#xff08;RuoYi&#xff09;作为一个基于Spring Boot和MyBatis的快速开发平台&#xff0c;提供了强大的代码生成器功能。通过代码生成器&#xff0c;开发者可以迅速创建基础的CRUD&#xff08;增删改查&#xff09;代码&#xff0c;大幅提高开发效率。本文将详细介绍…

电池簇、PCS、电芯之间包含关系

在储能系统中&#xff0c;电池簇&#xff08;Battery Pack&#xff09;、功率转换系统&#xff08;Power Conversion System, PCS&#xff09;、电芯&#xff08;Cell&#xff09;之间存在明确的包含和组成关系。以下是这些组件之间的标准层级关系&#xff1a; 电芯&#xff0…

全网最全网络基础思维导图合集(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;它可以成为我们的好…

设置环境变量,忽略yarn对node的版本检查

cmd set YARN_IGNORE_NODE1 PowerShell $env:YARN_IGNORE_NODE1 bash export YARN_IGNORE_NODE1

苹果CMS:通用清理后门排查

注意&#xff1a;为了安全起见 每次发现被挂马后应该用以下方法来处理&#xff01;&#xff01;&#xff01; 入侵可能在数据库挂js&#xff0c;可能在网站目录任何角落留下php后门&#xff0c;用以下方法可以快速清理干净php后门&#xff0c;不用一个一个文件去分析。 1、备…

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

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

OpenAI协作为评估网络安全LLM提供的14条建议

大型语言模型&#xff08;LLMs&#xff09;在摄取、合成和总结知识方面表现出非凡的能力&#xff0c;但同时在完成实际任务时也表现出明显的局限性。网络安全是一个值得注意的领域&#xff0c;它为利用 LLMs 带来了机遇和风险。LLMs 可以使网络安全专家在预防和阻止攻击时更加高…

文件自动同步备份-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…