阻塞队列的实现(线程案例)
一.什么是阻塞队列?
1.如果对于一个满的队列,还要把元素入队列,此时这个队列就会阻塞等待,一直阻塞到这个队列不满为止,从而把这个元素入队列!
2.如果对于一个空的队列,还要从队列拿出元素,此时这个队列就会阻塞等待,一直阻塞到这个队列不空为止,从而把这个元素拿出队列!
二.阻塞队列有什么作用:
1.解耦合作用
什么是耦合度:
耦合度高:就是模块之间联系比较紧密,彼此之间互相影响
耦合度低:就是模块之间联系没有那么紧密,也就是模块之间影响小。
此时引入阻塞队列,就可以有效降低模块之间的耦合度,起到了解耦合的作用!!
看图👇


2.削峰填谷作用

三.代码的实现
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;public class ThreadDemo11 {public static void main(String[] args) throws InterruptedException {BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);queue.put("666");String s=queue.take();System.out.println(s);s=queue.take();System.out.println(s);}
}
此时阻塞等待👇

四.自己模拟实现
//实现阻塞队列
class MyBlockingQueue{//这个是模拟实现队列private String[] elems = null;private int head = 0;private int tail = 0;private int size = 0;private Object locker = new Object();//实现构造方法👇public MyBlockingQueue(int capacity){elems = new String[capacity];}//放进元素public void put (String elem) throws InterruptedException {synchronized (locker){//超出队列长度!//使用while循环,是防止线程唤醒后只判断一次,让被唤醒的线程再判断一次while(size >= elems.length){locker.wait();}//往这里加元素!!!elems[tail] = elem;tail++;//这里面是循环队列,可使这块空间能够被循环利用!,所以需要tail = 0;if(tail == elems.length){tail = 0;}size++;locker.notify();}}//拿出元素public String take() throws InterruptedException {String elem = null;//队列里面没有元素,阻塞等待synchronized (locker){while(size == 0){locker.wait();}//拿出一个元素elem = elems[head];head++;if(head == elems.length){head = 0;}size--;locker.notify();}return elem;}}public class ThreadDemo10 {public static void main(String[] args) {MyBlockingQueue myBlockingQueue = new MyBlockingQueue(1000);//创建两个线程实现生产者和消费者模型Thread t1 =new Thread(()->{int n = 1;while(true){try {myBlockingQueue.put(n+"");System.out.println("生产元素"+n);n++;} catch (InterruptedException e) {throw new RuntimeException(e);}}});Thread t2 = new Thread(()->{while(true){try {String n = myBlockingQueue.take();System.out.println("消费元素"+n);Thread.sleep(500);} catch (InterruptedException e) {throw new RuntimeException(e);}}});//线程的启动!!t1.start();t2.start();}
}
代码中的一些问题

是否能够把里面这个while改成if👇
if(size >= elems.length){locker.wait();}
答案是不能的,为什么呢
假设这个队列的容量是1,且此时容量已满。假设有3个线程t1,t2、t3.
t1和t2都调用put(),此时t1线程进入wait()状态,由于wait()状态,t1线程释放了锁。然后
t2也进入了锁里面,进入wait()状态,也释放了锁。
t3线程执行take(),从线程中拿出了一个元素,然后进行notify(),随机唤醒了其中一个线程,假设唤醒了t1线程,t1线程把一个元素放进了队列,此时队列满了,然后notify(),唤醒了t2
线程,由于if操作已经执行过了,所以它要把元素放进队列,由于队列容量为1,所以t2无法把元素放进队列中,此时代码便出现了问题。
由此可见,使用while()可以使线程唤醒之后,再判断一次条件,进而避免了线程安全的问题!
五.生产者-消费者模型
这就可以使用阻塞队列来完成

此时这个生产元素的速度要比消费元素速度要快,所以队列会先满了,然后阻塞等待,最后就是消费一个元素,生产一个元素,趋于平衡。

那么就会有人说,队列的容量不是1000,为什么会出现1001
原因就在于:线程的调度是不确定的。
当生产元素1000已经达到了队列的容量,这是毋庸置疑的。然后线程进行消费元素,然后notify(),唤醒了生产元素的线程,此时这个消费元素还没有打印,然后这个生产元素的线程打印了生产元素1001。
相关文章:
阻塞队列的实现(线程案例)
一.什么是阻塞队列? 1.如果对于一个满的队列,还要把元素入队列,此时这个队列就会阻塞等待,一直阻塞到这个队列不满为止,从而把这个元素入队列! 2.如果对于一个空的队列,还要从队列拿出元素&…...
http status是什么?常见的http状态码指的是什么意思?
HTTP 状态码 HTTP 状态码(HTTP Status Code)是服务器在响应客户端请求时返回的一个三位数字代码,用于表示请求的处理结果。HTTP 状态码是 HTTP 协议的一部分,帮助客户端(如浏览器或应用程序)了解请求是否成…...
react组件分离,降低耦合
分离前 分离后...
【AI】AI白日梦+ChatGPT 三分钟生成爆款短视频
引言 随着人工智能(AI)技术的快速发展,AI在各个领域都展现出了强大的应用潜力。其中,自然语言处理技术的进步使得智能对话系统得以实现,而ChatGPT作为其中的代表之一,具有自动生成文本的能力,为…...
MYSQL的安装教程
mysql安装分为:普通安装和压缩包安装 压缩包安装很多会存在安装失败的情况,所以我这里就用了普通安装 一、官网下载安装包 www.mysql.com 点击DOWNLOADS: 进入社区版本下载: 点击最下面一行进行下载: 选择第二个离…...
深入解析 C# 中的泛型:概念、用法与最佳实践
C# 中的 泛型(Generics) 是一种强大的编程特性,允许开发者在不预先指定具体数据类型的情况下编写代码。通过泛型,C# 能够让我们编写更灵活、可重用、类型安全且性能优良的代码。泛型广泛应用于类、方法、接口、委托、集合等多个方…...
NUMA架构介绍
NUMA 架构详解 NUMA(Non-Uniform Memory Access,非统一内存访问) 是一种多处理器系统的内存设计架构,旨在解决多处理器系统中内存访问延迟不一致的问题。与传统的 UMA(Uniform Memory Access,统一内存访问…...
数据安全VS创作自由:ChatGPT与国产AI工具隐私管理对比——论文党程序员必看的避坑指南
文章目录 数据安全VS创作自由:ChatGPT与国产AI工具隐私管理对比——论文党程序员必看的避坑指南ChatGPTKimi腾讯元宝DeepSeek 数据安全VS创作自由:ChatGPT与国产AI工具隐私管理对比——论文党程序员必看的避坑指南 产品隐私设置操作路径隐私协议ChatGPT…...
python爬虫:python中使用多进程、多线程和协程对比和采集实践
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 1. 多进程爬虫1.1 python多进程样例1.2 实现多进程爬虫2. 多线程爬虫2.1 python多线程样例2.2 实现多线程爬虫3. 协程爬虫3.1 python协程样例3.2 实现协程爬虫在网络爬虫中,为了提高抓取效率,常常需要使用多进程、多线…...
《OpenCV》—— dlib库
文章目录 dlib库是什么?OpenCV库与dlib库对比dlib库安装dlib——人脸应用实例——人脸检测dlib——人脸应用实例——人脸关键点定位dlib——人脸应用实例——人脸轮廓绘制 dlib库是什么? OpenCV库与dlib库对比 dlib库安装 dlib——人脸应用实例——人脸检…...
Linux搜索---find
find搜索 find 命令的核心功能是在指定的目录路径下,递归地搜索文件和目录,并且可以根据多种条件对搜索结果进行筛选,还能对符合条件的文件和目录执行特定操作。 一、基础语法结构 find [起始目录] [匹配条件] [执行操作] # 基本示例 find…...
python之爬虫入门实例
链家二手房数据抓取与Excel存储 目录 开发环境准备爬虫流程分析核心代码实现关键命令详解进阶优化方案注意事项与扩展 一、开发环境准备 1.1 必要组件安装 # 安装核心库 pip install requests beautifulsoup4 openpyxl pandas# 各库作用说明: - requests&#x…...
Blender常用快捷键的汇总
一、基础操作 全选/取消全选:A(全选)、AA(连续按两次A取消全选)复制物体:Shift D(复制后需点击确认位置)移动物体:G(按X/Y/Z可约束轴向移动)旋转…...
鸿蒙启动页开发
鸿蒙启动页开发 1.1 更改应用名称和图标 1.更改应用图标 找到moudle.json5文件,找到应用启动的EntryAbility下面的icon,将原来的图标改成自己设置的即可 2.更改应用名称 3.效果展示 2.1 广告页面开发 3.1 详细介绍 3.1.1 启动页面 import { PrivacyDialog } fr…...
Unity 文字高度自适应
期望 文字有字号限制,输入文字文字后先判断高度是否适用于限制字号,若处于最小字号时高度任不适用,则调整RectTransform 的高度。 核心代码 每次输入文字时先将字号设定为原始字号。 comp.fontSize fontSize; comp.text content; 拓展T…...
Teaching Small Language Models Reasoning throughCounterfactual Distillation
2024.emnlp-main.333.pdfhttps://aclanthology.org/2024.emnlp-main.333.pdf 1.概述 大型语言模型(LLM),如GPT-3,在各种下游任务中表现出色,包括通过链式思维(CoT)进行问题解答。CoT鼓励模型在解决问题时生成中间推理步骤。尽管LLM取得了成功,但由于模型大小的限制,其…...
快速开始React开发(一)
快速开始React开发(一) React是一个JavaScript库,用于构建交互式网站,并且能够快捷创建SPA(Single Page App),其组件化的思想也是被一再传播,无论是普通的Web网站还是嵌入移动端交互…...
2025最新Transformer模型及深度学习前沿技术应用
第一章、注意力(Attention)机制 1、注意力机制的背景和动机(为什么需要注意力机制?注意力机制的起源和发展里程碑)。 2、注意力机制的基本原理(什么是注意力机制?注意力机制的数学表达与基本公…...
极狐GitLab 正式发布安全版本17.9.1、17.8.4、17.7.6
本分分享极狐GitLab 补丁版本 17.9.1、17.8.4、17.7.6 的详细内容。这几个版本包含重要的缺陷和安全修复代码,我们强烈建议所有私有化部署用户应该立即升级到上述的某一个版本。对于极狐GitLab SaaS,技术团队已经进行了升级,无需用户采取任何…...
[环境搭建篇] Windows 环境下如何安装Docker工具
Windows 环境下如何安装Docker工具 1. 检查系统要求2. 启用WSL 2和虚拟化步骤一:启用WSL步骤二:启用虚拟化(Hyper-V)步骤三:安装WSL 2内核 3. 安装Docker Desktop4. 配置Docker5. 家庭版用户替代方案6. 常见问题解决问…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
