阻塞队列-生产者消费者模型
- 阻塞队列介绍
- 标准库阻塞队列使用
- 基于阻塞队列的简单生产者消费者模型。
- 实现一个简单型阻塞队列 (基于数组实现)
阻塞队列介绍
不要和之前学多线程的就绪队列搞混;
阻塞队列:也是一个队列,先进先出。带有特殊的功能 ;阻塞
1:如果队列为空,执行出队列操作,就会阻塞阻塞到另一个线程往队列里添加元素(队列不空)为止
2:如果队列满了,执行入队列操作,也会阻塞阻塞到另一个线程从队列取走元素位置(队列不满)
消息队列:
先简单介绍消息队列:特殊的队列,相当于在阻塞队列的基础上,加上一个消息类型,按照类别进行先进先出。
因为这个消息队列使用起来太香;所以有大佬把这样的数据结构单独实现成一个程序;可以单独的部署到一组服务器上。使储存、转发能力大大提升。现在已经发展可以和mysql、redis相提并论的一个重要组件。
消息队列之所以这么好用和阻塞队列阻塞特性关系非常大;基于这种特性可以实现 “生产者消费者模型”
生产者消费者模型(常用的并发设计模式):比如包饺子;一个人负责制作饺子皮;一个人负责包;一个人负责下锅。不会说每个人单独包一个饺子,这样会导致撵面杖不够用,影响效率。两个好处。
1:实现发送方与接收方之间的解耦。
比如下面这种是耦合度比较高;A要调用B(A把请求转发给B处理,B把结果反馈给A),A得知道B的存在。如果B挂了,很容易引起A的bug。。如果你要增加一个C服务器,对A也需要修改代码,对A又得重新测试等又不知道是否改动A会对B有影响。
这种模型下;A、B耦合就降低很多;A中无B,B中无A的代码。两边有一方挂了都互相没任何影响;因为阻塞队列是正常的。B挂了,A仍然可以插入元素,满了就阻塞。A挂了,B仍然可以从队列获取元素;空了就阻塞。增加一个C服务器对A是无感知的。
2:削峰填谷的作用,保证系统的稳定性。
服务器开发也很类似;说不定坤哥唱一首只因你太美;热搜瞬间上来,很多用户给你发请求,如果没有削峰填谷的准备服务器很容易就挂掉。
标准库阻塞队列使用
Queue提供:入队列 offer 、出队列 poll、取队首元素 peek。
阻塞队列主要方法:入队列 put、出队列 take。抛异常阻塞得需要唤醒,空队列你再取就阻塞。阻塞队列也有offer和poll方法,但是这些是不带阻塞功能的。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.PriorityBlockingQueue;public class test14 {//标准库阻塞队列使用public static void main(String[] args) throws InterruptedException {
// BlockingDeque<String> q=new PriorityBlockingQueue<>() 基于堆;带有优先级阻塞队列BlockingDeque<String> q=new LinkedBlockingDeque<>();//基于链表实现
// BlockingDeque<String> q=new ArrayBlockingQueue<>(); 基于数组实现q.put("hello");System.out.println(q.take());//输出结果helloq.take();//空的时候取就会阻塞}
}
基于阻塞队列的简单生产者消费者模型。
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;public class test15 {//基于阻塞队列生产者消费者模型static int i=0;public static void main(String[] args) {BlockingDeque<Integer> blockingDeque=new LinkedBlockingDeque();Thread t1=new Thread(()->{//生产者while (true){try {blockingDeque.put(i);System.out.println(i);//生产的元素i++;Thread.sleep(500);//生产的很慢;消费者就得阻塞先;等到元素生产出来} catch (InterruptedException e) {throw new RuntimeException(e);}}});t1.start();Thread t2=new Thread(()->{//消费者while (true){try {System.out.println(blockingDeque.take());//消费的元素} catch (InterruptedException e) {throw new RuntimeException(e);}}});t2.start();}
}
执行效果
实现一个简单型阻塞队列 (基于数组实现)
先复习一下循环队列的实现。
public class test16 {//简单阻塞队列的实现;;先复习一遍循环队列private int[] elem;public int front;//队头public int rear;//队尾public test16(int k) {//创建这个对象,就有循环队列k大小数组elem=new int[k];}//判满;入队的前提条件,入队是满就直接返回。或者你在满的时候扩容,入之前判断是否满;如果满扩容再入public boolean isfull(){//怎么判;队尾+1 回到头。但是刚好队头在原点就会产生;位置相同;但是队尾+1的值不等于0.if((rear+1)%elem.length==front){return true;}return false;}//判空;出队的前提条件,出队是空直接返回public boolean isnull(){//对头==队就是空if(rear==front){return true;}
return false;}//入队方法;
public boolean offer1(int i) {if(isfull()){//满的情况返回入队失败return false;}//怎么入;是入在后面还是前面呢;队列尾入;这时候浪费的那个空间直接赋值进去;队尾往后移就好了elem[rear]=i;//会不会有点不合适;万一前面是没有元素呢rear=(rear+1)%elem.length; //这个队尾两种情况;第一种是单纯的加1;未到数组最后位置//比如我把前面空间删除。刚好到最后一个位置;就得回归原点。%elem.length//这里分开写效果会更好;rear++; if(rear>=elem.length){ rear=0; }//相比之下rear++;read=read%elem.length 。这个不易读,不直观;每次得理解好一会 。效率上又没有优势return true;}//出队方法public Int poll1(){//头出、怎么出呢。感觉不合理;出队应该返回这个元素.所以得先记录if(isnull()){return -1;}int value=front;front=(front+1)%elem.length;//往后移一位;elem.length避免逛了一圈return elem[value];}//获取队首public int peek1(){if(isnull()){return -1;}return elem[front];}//获取队尾public int Rear(){if(isnull()){return -1;}//得注意;不能直接返回read-1.因为如果read是原点;那么减1不就变成负一if(rear==0){return elem[elem.length-1];}elsereturn elem[rear-1];}public static void main(String[] args) {}
}
我们在此基础上加上阻塞功能就好了;也就是在多线程环境下使用;得保证线程安全。
在线程里使用这些方法时;如果出现符合阻塞条件情况就阻塞。
public class test17 {static int i;public static void main(String[] args) throws InterruptedException {//看看能不能基于我们创建这个阻塞队列实现生产者消费者模型my blockingDeque=new my(100);//这里浪费一个空间;达到98;就会阻塞Thread t1=new Thread(()->{//生产者while (true){try {blockingDeque.offer1(i);System.out.println(i);//生产的元素i++;Thread.sleep(50);//生产的很慢;消费者就得阻塞先;等到元素生产出来} catch (InterruptedException e) {throw new RuntimeException(e);}}});t1.start();Thread t2=new Thread(()->{//消费者while (true){try {System.out.println(blockingDeque.poll1());//消费的元素} catch (InterruptedException e) {throw new RuntimeException(e);}}});// t2.start();}}class my {//简单阻塞队列的实现;;先复习一遍循环队列private int[] elem;public int front;//队头public int rear;//队尾public my(int k) {elem = new int[k];}public void offer1(int i) throws InterruptedException {synchronized (this) {if (isfull()) {this.wait();}elem[rear] = i;rear = (rear + 1) % elem.length;// 这个 notify 唤醒 poll1 中的 waitthis.notify();}}//出队方法public int poll1() throws InterruptedException {synchronized (this) {if (isnull()) {this.wait();//两个wait是不可能同时触发的;因为一个队列不可能既是空又是满。只要this是同一个对象就不会.}int value = front;front = (front + 1) % elem.length;// 这个 notify 唤醒 offer1 中的 waitthis.notify();return elem[value];}}public boolean isfull() {if ((rear + 1) % elem.length ==front) {return true;}return false;}public boolean isnull() {//队头==队尾就是空if (rear == front) {return true;}return false;}}
上述代码还有一丝丝的瑕疵;offer1中wait被唤醒的时候;if的条件一定就不成立?(也就是队列一定是不满的?)
我们当前代码是取元素的时候;就唤醒,是不存在这个问题。万一其它操作也可能唤醒这个wait;但是情况又是队列不满的呢?
所以我们改成
whlie (isnull()) {this.wait();}
相关文章:

阻塞队列-生产者消费者模型
阻塞队列介绍标准库阻塞队列使用基于阻塞队列的简单生产者消费者模型。实现一个简单型阻塞队列 (基于数组实现) 阻塞队列介绍 不要和之前学多线程的就绪队列搞混; 阻塞队列:也是一个队列,先进先出。带有特殊的功能 &…...

Vector Art - 矢量艺术
什么是矢量艺术? 矢量图形允许创意人员构建高质量的艺术作品,具有干净的线条和形状,可以缩放到任何大小。探索这种文件格式如何为各种规模的项目提供创造性的机会。 什么是矢量艺术作品? 矢量艺术是由矢量图形组成的艺术。这些图形是基于…...
ruoyi-nbcio增加flowable流程待办消息的提醒,并提供右上角的红字数字提醒(一)
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 1、数据库表方面 在原来sys_notice修改基础上增加一个表叫sys_notice_send 表结构如下: DROP …...

数据结构:二叉树的基本概念
文章目录 1. 二叉树的定义2. 二叉树的特点3. 特殊二叉树斜树满二叉树完全二叉树 4. 二叉树的性质 1. 二叉树的定义 如果我们猜一个100以内的数字,该怎么猜才能理论最快呢? 第一种方式:从1,2一直猜到100, 反正数字都是100以内,总能猜到的 第二种方式:先猜50,如果比结果小,猜75…...
利用Socks5代理IP加强跨界电商爬虫的网络安全
随着跨界电商的兴起,爬虫技术在这个领域变得越来越重要。然而,网络安全一直是一个值得关注的问题。在本文中,我们将讨论如何利用代理IP和Socks5代理来增强跨界电商爬虫的网络安全,确保稳定和可靠的数据采集,同时避免封…...

Spring学习笔记6 Bean的实例化方式
Spring学习笔记5 GoF之工厂模式_biubiubiu0706的博客-CSDN博客 Spring为Bean提供了多种实例化方式,通常包括4中(目的:更加灵活) 1.通过构造方法实例化 2.通过简单工厂模式实例化 3.通过factory-bean实例化 4.通过FactoryBean接口实例化 新建模块 spring-005 依赖 <!--S…...
大二毕设.3-网盘系统-用户模块讲解
目录 模块功能介绍 具体实现讲解 constants层:存放用户模块常量类 entity层:存放实体类,与数据库中的属性值基本保持一致 mapper层:对数据库进行数据持久化操作 service层:业务逻辑层,主要是针对具体…...

(Vue2)智慧商城项目
新增两个目录api、utils api接口模块:发送ajax请求的接口模块 utils工具模块:自己封装的一些工具方法模块 第三方组件库vant-ui PC端:element-ui(element-plus) ant-design-vue 移动端:vant-ui Mint UI…...

Nginx实战
虚拟主机 虚拟主机指的就是⼀个独⽴的站点,具有独⽴的域名,有完整的www服务,例如⽹站、FTP、邮件等 。Nginx⽀持多虚拟主机,在⼀台机器上可以运⾏完全独⽴的多个站点。⼀些草根流量站⻓,常会搭建个⼈站点进⾏资源分享交…...
day-57 代码随想录算法训练营(19)动态规划 part 17
647.回文子串 思路:动态规划 1.dp存储:判断以i开始,j结尾的字符串是否是回文串2.动态转移方程:当s[i]s[j]时,如果j-i<1,d[i][j]true; 如果 dp[i1][j-1]true,那么dp[i][j…...

在项目中,关于前端实现数据可视化的技术选择
前言 在项目中,数据可视化以图表、报表类型为主。 需求背景 技术框架是Vue2.x版本,组件库是Ant Design of Vue能够支撑足够多的图表类型开发图表大小/位置能够随意变动图表样式需要支持丰富多样的用户配置强大、开放的图表语法支持复杂的数据可视化场景…...

DT 卡通材质学习 一
渐变着色器 相交线 笔刷和卡通结合使用 修改器...
【游戏引擎架构】6.2 资源管理器
资源管理器可以分为离线部分系统和运行时系统 文章目录 离线资源管理数据库资产管道 运行时资源管理文件结构内存管理文件间引用 离线资源管理 数据库 UE的数据库可以直接浏览、编辑资产,看到运行时的状态;但也存在两个较大的缺点: 版本管…...

spring的ThreadPoolTaskExecutor装饰器传递调用线程信息给线程池中的线程
概述 需求是想在线程池执行任务的时候,在开始前将调用线程的信息传到子线程中,在子线程完成后,再清除传入的数据。 下面使用了spring的ThreadPoolTaskExecutor来实现这个需求. ThreadPoolTaskExecutor 在jdk中使用的是ThreadPoolExecutor…...

转载 - 洞察问题本质,解决工作难题
作者:关苏哲 高效管理者的三大技能 问题界定的6个问题 1.你所需要解决的问题是什么? 2.你为什么需要解决这个问题? 3.你期待的理想结果是什么? 4.这个问题包括哪些子问题? 5.你曾经尝试过哪些解决方式?…...

关于计算机找不到d3dx9_43.dll,无法继续执行代码修复方法
d3dx9_43.dll是一个动态链接库文件,它是DirectX的一个组件,主要用于处理游戏中的图形、声音等多媒体元素。当这个文件丢失时,可能会导致以下问题: 1. 游戏无法正常运行:由于d3dx9_43.dll负责处理游戏中的多媒体元素&a…...

《从零开始的Java世界》01基本程序设计
《从零开始的Java世界》系列主要讲解Javase部分,从最简单的程序设计到面向对象编程,再到异常处理、常用API的使用,最后到注解、反射,涵盖Java基础所需的所有知识点。学习者应该从学会如何使用,到知道其实现原理全方位式…...

【数据开发】数据全栈知识架构,数据(平台、开发、管理、分析)
文章目录 一、数据全栈知识架构1、数据方法(思维,统计学,实践,北极星)2、数据工具:数据仓库3、数据规范 二、数据分析工具1、大数据平台2、数据开发:入库计算(重点)3、数…...

基于STM32的宠物托运智能控制系统的设计(第十七届研电赛)
一、功能介绍 使用STM32作为主控设备,通过DHT11温湿度传感器、多合一空气质量检测传感器以及压力传感器对宠物的托运环境中的温湿度、二氧化碳浓度和食物与水的重量进行采集,将采集到的信息在本地LCD显示屏上显示,同时,使用4G模块…...

数据结构的奇妙世界:实用算法与实际应用
文章目录 数据结构和算法的基本概念数据结构数组链表栈队列树图 算法 常见的数据结构和算法排序算法快速排序示例 数据结构的应用数据库管理系统图像处理网络路由 数据结构和算法的性能分析时间复杂度空间复杂度 如何更好地编写代码避免常见错误结论 🎉欢迎来到数据…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...

软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...
2025.6.9总结(利与弊)
凡事都有两面性。在大厂上班也不例外。今天找开发定位问题,从一个接口人不断溯源到另一个 接口人。有时候,不知道是谁的责任填。将工作内容分的很细,每个人负责其中的一小块。我清楚的意识到,自己就是个可以随时替换的螺丝钉&…...
GeoServer发布PostgreSQL图层后WFS查询无主键字段
在使用 GeoServer(版本 2.22.2) 发布 PostgreSQL(PostGIS)中的表为地图服务时,常常会遇到一个小问题: WFS 查询中,主键字段(如 id)莫名其妙地消失了! 即使你在…...

欢乐熊大话蓝牙知识17:多连接 BLE 怎么设计服务不会乱?分层思维来救场!
多连接 BLE 怎么设计服务不会乱?分层思维来救场! 作者按: 你是不是也遇到过 BLE 多连接时,调试现场像网吧“掉线风暴”? 温度传感器连上了,心率带丢了;一边 OTA 更新,一边通知卡壳。…...

智警杯备赛--excel模块
数据透视与图表制作 创建步骤 创建 1.在Excel的插入或者数据标签页下找到数据透视表的按钮 2.将数据放进“请选择单元格区域“中,点击确定 这是最终结果,但是由于环境启不了,这里用的是自己的excel,真实的环境中的excel根据实训…...