多线程学习之生产者和消费者与阻塞队列的关系
生产者和消费者
概述:
生产者消费者问题,实际上主要是包含了两类线程:
- 生产者线程用于生产数据
- 消费者线程用于消费数据
生产者和消费者之间通常会采用一个共享的数据区域,这样就可以将生产者和消费者进行解耦,
两者都不需要互相关注对方的
方法:
Object类的等待和唤醒方法
| 方法名 | 说明 |
|---|---|
| void wait() | 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法 |
| void notify() | 唤醒正在等待对象监视器的单个线程 |
| void notifyAll() | 唤醒正在等待对象监视器的所有线程 |
案例需求:
-
桌子类(Desk):定义表示双吉芝士汉堡数量的变量,定义锁对象变量,定义标记桌子上有无双吉芝士汉堡的变量
-
生产者类(Cooker):实现Runnable接口,重写run()方法,设置线程任务
1.判断是否有双吉芝士汉堡,决定当前线程是否执行
2.如果有双吉芝士汉堡,就进入等待状态,如果没有双吉芝士汉堡继续执行,生产双吉芝士汉堡
3.生产双吉芝士汉堡之后,更新桌子上双吉芝士汉堡状态,唤醒消费者消费双吉芝士汉堡
-
消费者类(Foodie):实现Runnable接口,重写run()方法,设置线程任务
1.判断是否有双吉芝士汉堡,决定当前线程是否执行
2.如果没有双吉芝士汉堡,就进入等待状态,如果有双吉芝士汉堡,就消费双吉芝士汉堡
3.消费双吉芝士汉堡后,更新桌子上双吉芝士汉堡状态,唤醒生产者生产双吉芝士汉堡
-
测试类(Demo):里面有main方法,main方法中的代码步骤如下
创建生产者线程和消费者线程对象
分别开启两个线程
/*** @Author:kkoneone11* @name:Cooker* @Date:2023/8/27 18:55*/
public class Cooker extends Thread{private Desk desk;public Cooker(Desk desk){this.desk = desk;}// 生产者步骤:
// 1,判断桌子上是否有双吉芝士汉堡
// 如果有就等待,如果没有才生产。
// 2,把双吉芝士汉堡放在桌子上。
// 3,叫醒等待的消费者开吃。@Overridepublic void run(){while(true){synchronized (desk.getLock()){if(desk.getCount() == 0){break;}else {if(!desk.isFlag()){System.out.println("厨师正在制作双吉芝士汉堡");//生产双层吉士desk.setFlag(true);//叫醒麦门弟子干饭desk.getLock().notifyAll();}else{try{desk.getLock().wait();}catch (Exception e){e.printStackTrace();}}}}}}
}public class Foodie extends Thread{private Desk desk;public Foodie(Desk desk){this.desk = desk;}// 1,判断桌子上是否有双吉芝士汉堡。
// 2,如果没有就等待。
// 3,如果有就开吃
// 4,吃完之后,桌子上的双吉芝士汉堡就没有了
// 叫醒等待的生产者继续生产
// 双吉芝士汉堡的总数量减一@Overridepublic void run(){while(true){synchronized (desk.getLock()){if(desk.getCount() == 0){break;}else {if(desk.isFlag()){//有双层吉士System.out.println("麦门弟子疯狂炫吧");desk.setFlag(false);desk.getLock().notifyAll();desk.setCount(desk.getCount() -1);}else{//没有双层吉士 等待//使用什么对象当做锁,那么就必须用这个对象去调用等待和唤醒的方法.try {desk.getLock().wait();}catch (Exception e){e.printStackTrace();}}}}}}
}public class Demo {public static void main(String[] args) {Desk desk = new Desk();Foodie f = new Foodie(desk);Cooker c = new Cooker(desk);f.start();c.start();}
}
阻塞队列:
阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素
阻塞队列继承结构:

常见BlockingQueue的实现类:
- ArrayBlockingQueue: 底层是数组,有界
- LinkedBlockingQueue: 底层是链表,无界.但不是真正的无界,最大为int的最大值
方法:
实例:
public class Demo {public static void main(String[] args) throws Exception {// 创建阻塞队列的对象,容量为 1ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(1);// 存储元素arrayBlockingQueue.put("双层吉士");// 取元素System.out.println(arrayBlockingQueue.take());System.out.println(arrayBlockingQueue.take()); // 取不到会阻塞System.out.println("程序结束了");}
}
案例需求优化:
不再需要Desk这个类,改用阻塞队列
public class Cooker extends Thread{private ArrayBlockingQueue<String> bd;public Cooker(ArrayBlockingQueue<String> bd) {this.bd = bd;}
// 生产者步骤:
// 1,判断桌子上是否有汉堡包
// 如果有就等待,如果没有才生产。
// 2,把汉堡包放在桌子上。
// 3,叫醒等待的消费者开吃。@Overridepublic void run() {while (true) {try {bd.put("汉堡包");System.out.println("厨师放入一个汉堡包");} catch (InterruptedException e) {e.printStackTrace();}}}
}public class Foodie extends Thread{private ArrayBlockingQueue<String> bd;public Foodie(ArrayBlockingQueue<String> bd) {this.bd = bd;}@Overridepublic void run() {
// 1,判断桌子上是否有汉堡包。
// 2,如果没有就等待。
// 3,如果有就开吃
// 4,吃完之后,桌子上的汉堡包就没有了
// 叫醒等待的生产者继续生产
// 汉堡包的总数量减一while (true) {try {String take = bd.take();System.out.println("吃货将" + take + "拿出来吃了");} catch (InterruptedException e) {e.printStackTrace();}}}}public class Demo {public static void main(String[] args) {ArrayBlockingQueue<String> bd = new ArrayBlockingQueue<>(1);Foodie f = new Foodie(bd);Cooker c = new Cooker(bd);f.start();c.start();}
}
相关文章:
多线程学习之生产者和消费者与阻塞队列的关系
生产者和消费者 概述: 生产者消费者问题,实际上主要是包含了两类线程: 生产者线程用于生产数据消费者线程用于消费数据 生产者和消费者之间通常会采用一个共享的数据区域,这样就可以将生产者和消费者进行解耦, 两…...
JAVA语言代入电商平台api接口拼多多根据关键词获取商品列表示例
拼多多根据关键词获取商品接口的意义; 实现商品搜索:通过关键词搜索商品API接口,电商平台可以为消费者提供一个简单、快捷的商品搜索功能。用户只需输入关键词,就可以得到与该关键词相关的商品列表。 提供便捷的商品搜索服务&…...
Centos7更新glibc2.18
Centos7更新glibc2.18 查看glibc版本下载解压glibc2.18编译安装结果验证 查看glibc版本 # 查看glibc版本 ldd --version下载解压glibc2.18 参考: https://blog.csdn.net/qq_39295044/article/details/86685789 https://blog.csdn.net/myhes/article/details/106923039 # 下载…...
QT初学者该安装qt creator哪个版本?
对于Qt初学者,建议安装最新版本的Qt Creator。Qt Creator是Qt官方提供的集成开发环境(IDE),用于开发Qt应用程序。每个Qt版本都会配套提供对应的Qt Creator版本,确保兼容性和稳定性。同时,选择合适的Qt版本也…...
VR智慧校园资中控管理平台综合提升了课堂教学质量
随着越来越多高校在课堂中引进VR虚拟仿真实训系统,为了方便老师对全班同学进行高效率地管理,VR中控平台应运而生。下面为您详细介绍VR中控平台在课堂教学中的应用优势。 VR中控系统安装在教师总控端,融合了课件、视频、3D动画等丰富的教学资源…...
【Go 基础篇】Go语言中的数组:初识与应用
Go语言以其简洁、高效和强大的特性在编程界广受欢迎。数组作为一种基本的数据结构,在各种应用场景中扮演着重要角色。本文将引入Go语言中的数组,介绍其特点、创建、初始化以及基本应用,为你打开数组的大门。 前言 数组是一种固定大小的数据…...
(vue)el-table 怎么把表格列中相同的数据 合并为一行
(vue)el-table 怎么把表格列中相同的数据 合并为一行 效果: 文档解释: 写法: <el-table:data"tableData"size"mini"class"table-class"borderstyle"width:100%"max-height"760":span-…...
精准高效农业作业,植保无人机显身手
中国作为农业大国,拥有约18亿亩的农田,每年都需要进行种子喷洒和农药施用等农业作业,对于普通农户来说,这是一项耗时耗力的工程,同时,人工喷洒农药极易造成农药慢性中毒,对农民的身体健康产生极…...
大集合拆分成多个小集合
文章目录 1. 场景2. 拆分集合方法(写了三种)3. 格式化打印方法 1. 场景 在数据库批量操作时,有可能数据量过大,不能一次性操作,所以需要将大集合拆分为多个小集合进行多次操作 2. 拆分集合方法(写了三种&…...
linux————LVS集群
目录 一、集群概述 一、负载均衡技术类型 二、负载均衡实现方式 二、LVS结构 一、三层结构 二、架构对象 三、LVS工作模式 四、负载均衡算法 一、静态负载均衡 二、动态负载 五、ipvsadm命令详解 六、LVS配置 一、基础配置 二、实现NAT模型搭建 配置IP地址 安装…...
软考高级系统架构设计师系列论文七十一:论行业应用软件系统的开发规划
软考高级系统架构设计师系列论文七十一:论行业应用软件系统的开发规划 一、软件系统相关知识二、摘要三、正文四、总结一、软件系统相关知识 软考高级系统架构设计师系列之:系统开发基础知识...
vue2 自定义指令,插槽
一、学习目标 1.自定义指令 基本语法(全局、局部注册)指令的值v-loading的指令封装 2.插槽 默认插槽具名插槽作用域插槽 二、自定义指令 1.指令介绍 内置指令:v-html、v-if、v-bind、v-on… 这都是Vue给咱们内置的一些指令,…...
oracle超详细语法和备份工具
oracle基础语法 在 Oracle 开发中,客户端把 SQL 语句发送给服务器,服务器对 SQL 语句进行编译、执行,把执行的结果返回给客户端。常用的SQL语句大致可以分为五类:数据定义语言(DDL),包括 CREAT…...
Redis的持久化机制是什么?各自的优缺点?
Redis拥有两种持久化机制:RDB(Redis Database)和AOF(Append-Only File)。 1.RDB(Redis Database)持久化机制 RDB是Redis的默认持久化方式,它通过将Redis在某个时间点的数据状态保存到磁盘上的二进制文件中。该文件是一个快照(snapshot),包含…...
机器学习:什么是分类/回归/聚类/降维/决策
目录 学习模式分为三大类:监督,无监督,强化学习 监督学习基本问题 分类问题 回归问题 无监督学习基本问题 聚类问题 降维问题 强化学习基本问题 决策问题 如何选择合适的算法 我们将涵盖目前「五大」最常见机器学习任务:…...
算法通关村第5关【白银】| 哈希和栈经典算法题
1.两个栈实现队列 思路:两个栈,一个输入栈,一个输出栈。 当需要输入的时候就往inStack中插入,需要输出就往outStack中输出,当输出栈是空就倒出输入栈的数据到输出栈中,这样就保证了后插入的数据从栈顶倒入…...
CrystalNet .Net VCL for Delphi Crack
CrystalNet .Net VCL for Delphi Crack VCL或更为人所知的可视化组件库是基于一个面向对象的框架,什么是用户对开发人员和事件的Microsoft Windows应用程序的接口。可视化组件库是用对象Pascal编写的。它主要是为使用Borland而开发的,它具有与Delphi以及…...
云计算在线实训系统建设方案
一、 人工智能与云计算系统概述 人工智能(Artificial Intelligence,简称AI)是一种模拟人类智能的科学和工程,通过使用计算机系统来模拟、扩展和增强人类的智能能力。人工智能涉及多个领域,包括机器学习、深度学习、自然…...
C++ 珠心算测验
珠心算是一种通过在脑中模拟算盘变化来完成快速运算的一种计算技术。珠心算训练, 既能够开发智力,又能够为日常生活带来很多便利,因而在很多学校得到普及。 某学校的珠心算老师采用一种快速考察珠心算加法能力的测验方法。他随机生成一个正整…...
prometheus+cadvisor监控docker容器
一、安装cadvisor docker pull google/cadvisor:latest二、运行容器 docker run -d \--volume/:/rootfs:ro \--volume/var/run:/var/run:rw \--volume/sys:/sys:ro \--volume/var/lib/docker/:/var/lib/docker:ro \--publish8088:8080 \--detachtrue \--namecadvisor \--priv…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
