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

并发集合类(4):ArrayBlockingQueue

什么是ArrayBlockingQueue?

ArrayBlockingQueueJUC里的一个有界阻塞队列,底层基于数组实现,非常适合用来做生产者-消费者模型

ArrayBlockingQueue的设计和用途和LinkedBlockingQueue类似,只是底层实现不同。

相同之处:

  1. 都实现了Blocking接口,支持阻塞的puttake方法
  2. 内部使用ReentrantLock来实现线程安全
  3. 都可以设置容量,作为有界队列

不同之处:

  1. 底层一个是数组实现,一个是链表实现
  2. LinkedBlockingQueue可以作为无界队列来使用
  3. ArrayBlockingQueue内部只有一把锁,读写互斥,因此并发度更低,而LinkedBlockingQueue内部有两把锁,读写并行,并发度更高。
  4. ArrayBlockingQueue可以实现公平队列

ArrayBlockingQueue的内部数据结构

final Object[] items; ## int takeIndex; int putIndex; int count; final ReentrantLock lock; private final Condition notEmpty; private final Condition notFull; transient Itrs itrs;

items是真正存放队列元素的数组,逻辑上是环形数组。

takeIndexputIndex是位置指针,一个指向队头,一个指向队尾。count则是用来判空和满的。

lock用于内部并发控制,notEmptynotFull是对应的条件队列。

itrs管理所有活跃迭代器的共享状态。

ArrayBlockingQueue的方法

构造方法

public ArrayBlockingQueue(int capacity) { this(capacity, false); } public ArrayBlockingQueue(int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); this.items = new Object[capacity]; lock = new ReentrantLock(fair); notEmpty = lock.newCondition(); notFull = lock.newCondition(); }

ArrayBlockingQueue的构造方法中,可以设置队列的大小以及是否为公平队列。

offer操作

效果同LinkedBlockingQueueoffer操作。

public boolean offer(E e) { Objects.requireNonNull(e); final ReentrantLock lock = this.lock; lock.lock(); try { if (count == items.length) return false; else { enqueue(e); return true; } } finally { lock.unlock(); } } private void enqueue(E e) { // assert lock.isHeldByCurrentThread(); // assert lock.getHoldCount() == 1; // assert items[putIndex] == null; final Object[] items = this.items; items[putIndex] = e; if (++putIndex == items.length) putIndex = 0; count++; notEmpty.signal(); }

  1. 加锁
  2. 如果队列已满,则直接返回false
  3. 加入队列,唤醒阻塞的take线程
  4. 解锁

put操作

put操作也与LinkedBlockingQueue类似

public void put(E e) throws InterruptedException { Objects.requireNonNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); enqueue(e); } finally { lock.unlock(); } }

  1. 加锁
  2. 当队列已满的时候,放入条件队列中
  3. 入队
  4. 解锁

poll操作

public E poll() { final ReentrantLock lock = this.lock; lock.lock(); try { return (count == 0) ? null : dequeue(); } finally { lock.unlock(); } }

  1. 加锁
  2. 如果队列为空,返回空值,否则出队
  3. 解锁

take操作

public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == 0) notEmpty.await(); return dequeue(); } finally { lock.unlock(); } }

  1. 加锁
  2. 如果队列为空,则进入条件队列
  3. 出队
  4. 解锁

size方法

public int size() { final ReentrantLock lock = this.lock; lock.lock(); try { return count; } finally { lock.unlock(); } }

ArrayBlockingQueuesize()方法是加锁的,因为count并没有被volatile所修饰,需要使用加锁的语义来获取最新的count

http://www.jsqmd.com/news/802962/

相关文章:

  • 医院患者管理软件哪个好? - 中媒介
  • 5分钟免费解锁Cursor Pro:彻底告别AI编程限制
  • 给STM32H743的FreeRTOS任务配个“文件管家”:实战整合FATFS的队列通信模型
  • 寄生电感容易被忽略,却是电路不稳定的隐形元凶
  • 博客等级升级啦
  • Android RTSP流播放实战:从VideoView到NodeMediaClient,三种方案保姆级配置与避坑指南
  • Simple Runtime Window Editor:突破游戏窗口分辨率限制的终极解决方案
  • 专业WZ文件编辑器Harepacker-resurrected:现代游戏资源编辑的完整解决方案
  • 盒马鲜生礼品卡回收价格指南,回收多少才不亏 - 淘淘收小程序
  • 纠结国际半导体展会哪家好?全球半导体展核心优势大盘点 - 品牌2026
  • 进口电磁阀选型指南:工业流体控制的可靠选择-米勒电磁阀 - 米勒阀门
  • CI/CD 流水线Runner配置
  • 凰标出世:中国文化不再只有一种声音@凤凰标志
  • 电源设计三大常识误区:效率、噪声与系统能效的深度解析
  • python之元组定义和函数
  • 消息撤回终结者:用RevokeMsgPatcher留住那些不该消失的对话
  • OpenClaw工具如何快速配置接入Taotoken平台
  • KeymouseGo完全指南:5分钟掌握桌面自动化的终极解决方案
  • Python POST请求与模拟登录实战:从表单分析到Gitee平台登录
  • 解读深圳奢侈品包包回收市场:迪奥、LV回收行情及正规机构推荐! - 奢侈品回收测评
  • 终极指南:5步安装Koikatu HF Patch解锁完整游戏体验
  • 用STM32F407的DCMI接口驱动AD9926:一个被忽视的高速并行ADC方案
  • minio 监控
  • 基于Chrome DevTools协议实现AI与浏览器实时交互的实践指南
  • 保姆级教程:用Python的ecg-qc库搞定心电信号质量评估(附6种SQI代码详解)
  • 开发预告:关于改造Hermes-agent这件事,我想说的比上一篇多得多
  • APK Installer完整指南:在Windows上快速安装Android应用的终极方案
  • 医疗人工智能系统哪里找? - 中媒介
  • 从AlphaGo到你的小游戏:如何用MCTS(蒙特卡洛树搜索)为你的五子棋项目加个‘智能大脑’
  • 从Pikachu靶场看SQL注入:新手如何用Burp Suite一步步挖出数据库里的秘密