当前位置: 首页 > news >正文

阻塞队列的使用和实现

阻塞队列是一种特殊的队列,其遵循“先入先出”的原则。

阻塞队列也是一种线程安全的数据结构,具有以下特性:

  • 队列为满,入队列产生阻塞,直至其他线程从队列中取走元素
  • 队列为空,出队列产生阻塞,直至其他线程往队列中插入元素

“生产者消费者模型”是阻塞队列的一个典型应用场景,该模型也是一个典型的开发模型。

生产者消费者模型

生产者消费者模型就是通过一个中间容器来解决生产者和消费者之间的强耦合问题。

这个中间容器通过阻塞队列实现,从而使生产者和消费者之间不进行直接通讯。

阻塞队列的作用:

  1. 阻塞队列相当于一个缓冲区,平衡了生产者和消费者的处理能力(削峰填谷)
  2. 阻塞队列使生产者和消费者之间解耦

阻塞队列的缺点:

  1. 引入队列以后,代码整体结构变复杂
  2. 程序执行效率有所影响

阻塞队列的使用

Java的标准库中,提供了现成的阻塞队列。

  • BlockingQueue是一个接口,真正实现的类有:LinkedBlockingQueue(链表实现),ArrayBlockingQueue(数组实现),PriorityBlockingQueue(堆实现)等等。
  • 队列的出操作是poll,入队列操作是offer,但是阻塞队列使用的分别时take和put,这两个方法是带有阻塞功能的出入队列操作。
public class demo1 { public static void main(String[] args) { //创建阻塞队列 BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(1000); //生产者线程 Thread producer = new Thread(() -> { int n = 0; while (true) { try { queue.put(n); System.out.println("生产元素 " + n); n++; } catch (InterruptedException e) { throw new RuntimeException(e); } } }, "procducer"); //消费者线程 Thread consumer = new Thread(() -> { while(true){ try { int n = queue.take(); System.out.println("消费元素 " + n); } catch (InterruptedException e) { throw new RuntimeException(e); } } }, "consumer"); producer.start(); consumer.start(); } }

阻塞队列的简单实现

  • 使用“循环队列”实现
  • 使用synchronized加锁保证线程安全
  • 注意这里的wait()搭配while使用,而不能搭配if使用,是由于notifyAll会将所有的wait唤醒,只有其中一个线程会put,而等到其他被唤醒的线程拿到锁之后,还需要确认一下容量是否已满,满的话还需要阻塞等待。
class BlockingQueue { private int[] item = new int[1000]; private volatile int head = 0; private volatile int tail = 0; private volatile int size = 0; //生产元素 public void put(int value) throws InterruptedException { synchronized (this) { while (size == item.length) { this.wait(); } item[tail] = value; tail++; if (tail == item.length) { tail = 0; } size++; notifyAll(); } } //消费元素 public int take() throws InterruptedException { synchronized (this) { while (size == 0) { this.wait(); } int ret = item[head]; head++; if(head == item.length){ head = 0; } size--; notifyAll(); return ret; } } //获取内部属性 public synchronized int getSize() { return size; } }
http://www.jsqmd.com/news/125726/

相关文章:

  • LangFlow网络安全态势感知系统雏形
  • 【SCI复现】电力系统储能调峰、调频模型研究(Matlab代码实现)
  • Orange Pi上运行EmuELEC的常见问题:快速理解
  • Redis常见面试
  • Topit:3步解决Mac窗口遮挡难题,让你的关键内容始终置顶
  • 轻松突破RPG Maker MV加密壁垒:全方位资源解密实战指南
  • OpenCVSharp:透视变换
  • 基于Java+大数据+SSM基于Hadoop的健康饮食推荐系统(源码+LW+调试文档+讲解等)/健康饮食建议系统/健康膳食推荐平台/健康饮食指导系统/营养饮食推荐系统
  • GeoJSON.io 免费在线地理编辑器:零基础快速上手终极教程
  • 抖音无水印下载神器:3分钟学会保存高清视频的终极方法
  • LangFlow情感分析仪表盘构建教程
  • 【重磅开源】让 Claude/GitHub Copilot 秒变你的 M365 私人助理!
  • 基于Java+大数据+SSM基于Hadoop的宁波旅游推荐周边商城实现与设计(源码+LW+调试文档+讲解等)/宁波旅游攻略/宁波旅游景点/宁波周边游/宁波商城推荐/宁波购物商城/旅游推荐系统
  • GeoJSON.io 地理数据编辑工具:从零基础到精通的完整操作指南
  • vue3+el-upload+多张图片(20MB左右)+图片压缩上传到后端+可限制条数+懒加载
  • 利用Wireshark深入理解ModbusTCP报文格式说明
  • 突破屏幕限制:Topit窗口置顶工具重新定义macOS多任务体验
  • Mac窗口管理终极利器:Topit让多任务处理效率翻倍 [特殊字符]
  • 终极Mac窗口置顶指南:如何用Topit告别多任务切换烦恼
  • 嵌入式图像转换工具终极使用指南
  • 123
  • Yolov8模型,使用pt跑正常,使用yaml跑得到的P、R、mAP等值均为0的问题
  • KeilC51与MDK同时安装后的License管理建议
  • Topit窗口置顶神器:告别多任务窗口混乱的终极方案
  • ESP32开发红外遥控家电中枢:新手教程(含代码)
  • 全球成膜助剂供应商有哪些?聚焦2025年全球成膜助剂供应商TOP榜单盘点 - 品牌2026
  • 如何快速掌握image2cpp:图像转字节数组的终极指南
  • yolo项目数据集路径缓存
  • 终极效率神器:5步掌握现代自动化工具的完整指南
  • macOS窗口管理终极方案:3步打造你的专属工作空间