AQS底层源码深度剖析-BlockingQueue
目录
AQS底层源码深度剖析-BlockingQueue
BlockingQueue定义
队列类型
队列数据结构
ArrayBlockingQueue
LinkedBlockingQueue
DelayQueue
BlockingQueue API
添加元素
检索(取出)元素
BlockingQueue应用队列总览图
AQS底层源码深度剖析-BlockingQueue【重点中的重点】
看源码前,先要明白Condition的含义:
BlockingQueue源码会涉及三个队列【重点掌握】:
put()源码剖析:
take()源码剖析:
总结:
AQS底层源码深度剖析-BlockingQueue
BlockingQueue定义
线程通信一个工具,在任意时刻,不管并发有多高,在单台JVM上,同一时间永远只能有一个线程能够对队列进行入队或者出队操作。
官方点说:BlockingQueue,是java.util.concurrent包提供的用于解决并发生产者-消费者问题的最有用的类,它的特性是在任意时刻只有一个线程可以进行take或put操作,并且BlockingQueue提供了超时return null的机制,在许多生产应用场景里都可以看到这个工具的身影。
应用场景:
线程池,springcloud-Eureka的三级缓存,Nacos,Netty,MQ
队列类型
- 无限队列 (unbounded queue ) - 几乎可以无限增长
- 有限队列 ( bounded queue ) - 定义了最大容量
队列数据结构
队列实质就是一种存储数据的结构
- 通常用链表或者数组实现
- 一般而言队列具备FIFO先进先出的特性,当然也有双端队列(Deque)优先级队列
- 主要操作:入队(EnQueue)与出队(Dequeue)
常见的4种阻塞队列
- ArrayBlockingQueue 由数组支持的有界队列
- LinkedBlockingQueue 由链接节点支持的可选有界队列
- PriorityBlockingQueue 由优先级堆支持的无界优先级队列
- DelayQueue 由优先级堆支持的、基于时间的调度队列
ArrayBlockingQueue
队列基于数组实现,容量大小在创建ArrayBlockingQueue对象时已定义好
数据结构如下图:

队列创建:
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>();
应用场景
在线程池中有比较多的应用,生产者消费者场景
工作原理
基于ReentrantLock保证线程安全,根据Condition实现队列满时的阻塞
LinkedBlockingQueue
是一个基于链表的无界队列(理论上有界)
BlockingQueue<String> blockingQueue = new LinkedBlockingQueue<>();
上面这段代码中,blockingQueue的容量将设置为Integer.MAX_VALUE
向无限容量的队列中添加元素的所有操作都将永远不会阻塞,因此它可以增长到非常大的容量(注意 这里不是说不会加锁保证线程安全,同样会加锁来保证同一时刻只会有一个线程对队列添加元素或取出元素成功)
使用无限容量的BlockingQueue设计生产者-消费者模型时最重要的是消费者应该能够像生产者向队列添加消息一样快的消费消息。否则存储消息数据的内存可能会填满,然后得到一个OutOfMemory异常
DelayQueue
由优先级堆支持的、基于时间的调度队列,内部基于无界队列PriorityQueue实现,而无界队列基于数组的扩容实现。
队列创建:
BlockingQueue<String> blockingQueue = new DelayQueue();
要求:
入队的对象必须要实现Delayed接口,而Delayed集成自Comparable接口
应用场景:
电影票
工作原理:
队列内部会根据时间优先级进行排序。延迟类线程池周期执行。
BlockingQueue API
BlockingQueue 接口的所有方法可以分为两大类:负责向队列添加元素的方法和检索(取出)这些元素的方法。在队列满/空的情况下,来自这两个组的每个方法的行为都不同。
添加元素
| 方法 | 说明 |
| add() | 如果插入成功则返回 true,否则抛出 IllegalStateException 异常 |
| put() | 将指定的元素插入队列,如果队列满了,那么会阻塞直到有空间插入 |
| offer() | 如果插入成功则返回 true,否则返回 false |
| offer(E e, long timeout, TimeUnit unit) | 尝试将元素插入队列,如果队列已满,那么会阻塞直到有空间插入 |
检索(取出)元素
| 方法 | 说明 |
| take() | 获取队列的头部元素并将其删除,如果队列为空,则阻塞并等待元素变为可用 |
| poll(long timeout, TimeUnit unit) | 检索并删除队列的头部,如有必要,等待指定的等待时间以使元素可用,如果超时,则返回 null |
在构建生产者 - 消费者程序时,这些方法是 BlockingQueue 接口中最重要的构建块。
BlockingQueue应用队列总览图
应用队列:存储消息数据的队列。无论是consumer还是producer,想要对应用队列中的消息数据进行操作(存入或取出)时,必须先获取到锁对象。如果获取不到锁,则无法操作。

(1)
极端情况下:
当producer把队列容量放满了,那么producer释放锁,producer阻塞,让consumer获取到锁 然后去消费消息数据
同理当consumer消费完队列中的消息数据,那么consumer会释放锁,consumer阻塞,让producer获取到锁,然后去生产并且加入消息数据到队列中
普通情况下:
当然应用队列中没有放满,consumer也可以消费取出数据 。队列数据没有被消费完时,producer也可以生产消息并且存入应用队列中。
(2) 当producer在同步队列中存入一个消息数据后,会进行通知consumer,consumer接收到通知,会从条件队列中转移到阻塞CLH队列,在CLH阻塞队列中的consumer会进行消费应用队列中存储的消息数据
AQS底层源码深度剖析-BlockingQueue【重点中的重点】
以下会深度剖析BlockingQueue的put()和take()方法的底层实现源码,一步步走完后会进行总结。如果不看源码,就没有任何的说服性。
看源码前,先要明白Condition的含义:
Condition的实现ConditionObject:
ConditionObject是AQS类的内部类,在BlockingQueue底层的实现中主要功能有:等待队列,等待和通知。
等待队列,等待和通知:源码中会使用到notEmpty和notFull
notEmpty: 消费者对应的等待队列。有啥用?当应用队列中的数据被消费完毕后,最后一次消费数据的消费者会释放掉自己持有的锁,然后调用notEmpty.await()加入到notEmpty等待队列的尾部。并且会调用notFull.signal()表示唤醒生产者等待队列中的一个节点加入到CLH阻塞队列中去[因为队列中没有数据啦,所以要唤醒生产者加入到CLH阻塞队列中]。
notFull:生产者对应的等待队列。有啥用?当应用队列中的空间已经被数据占满后,最后一次生产数据的生产者会释放掉自己持有的锁,然后调用notFull.await()加入到notFull等待队列的尾部。并且会调用notEmpty.signal()表示唤醒消费者等待队列中的一个节点加入到CLH阻塞队列中去[因为队列的空间被数据占满啦,所以要唤醒消费者加入到CLH阻塞队列中]。
补充:
其实唤醒也不是说只有当极端情况下(队列被占满或队列为空)才会进行唤醒消费者或生产者,其实每一次往队列中进行加入或取出数据都会导致各自的唤醒操作。
eg:加入一条数据会导致唤醒一个消费者等待队列中的消费者加入到CLH队列。取出一条数据时同理即可。
BlockingQueue源码会涉及三个队列【重点掌握】:
1.应用队列:
存放消息数据,模拟出的一个虚拟队列概念,可以认为是一个虚拟的不存在的存储结构,底层是使用数组进行存储插入应用队列的数据,以此模拟出一个应用队列。
2.CLH双端阻塞队列:存储封装当前线程对象对应的Node节点,是底层真实存在的一个队列
3.条件等待队列:这个就是上面Condition中记录的:notEmpty和notFull
put()源码剖析:
API层面调用put()方法其实就是生产者加入一条数据到应用队列
1.

2.

3.put方法解析
生产者插入一个数据到应用队列,以下为具体的分析过程:

对put()方法中的await()方法解析一下:


对put方法中的equeue()方法解析:

take()源码剖析:
API层面调用take()方法其实就是生产者从应用队列中取出一条数据
1.

2.

3.

对take()中的await方法解析:

对take()中的dequeue方法解析:

总结:
(1)记清楚三个队列
(2)明白Condition的含义
(3)画出图即可
其实也没啥,看懂了也挺简单的,关于这个源码的图,使用processon绘制:
ProcessOn Flowchart

相关文章:
AQS底层源码深度剖析-BlockingQueue
目录 AQS底层源码深度剖析-BlockingQueue BlockingQueue定义 队列类型 队列数据结构 ArrayBlockingQueue LinkedBlockingQueue DelayQueue BlockingQueue API 添加元素 检索(取出)元素 BlockingQueue应用队列总览图 AQS底层源码深度剖析-BlockingQueue【重点中的重…...
Kotlin协程:Flow的异常处理
示例代码如下:launch(Dispatchers.Main) {// 第一部分flow {emit(1)throw NullPointerException("e")}.catch {Log.d("liduo", "onCreate1: $it")}.collect {Log.d("liudo", "onCreate2: $it")}// 第二部分flow …...
qt下ffmpeg录制mp4经验分享,支持音视频(h264、h265,AAC,G711 aLaw, G711muLaw)
前言 MP4,是最常见的国际通用格式,在常见的播放软件中都可以使用和播放,磁盘空间占地小,画质一般清晰,它本身是支持h264、AAC的编码格式,对于其他编码的话,需要进行额外处理。本文提供了ffmpeg录…...
C#读取Excel解析入门-1仅围绕三个主要的为阵地,进行重点解析,就是最理性的应对上法所在
业务中也是同样的功能点实现。只是多扩展了很多代码,构成了项目的其他部分,枝干所在。但是有用的枝干,仅仅不超过三个主要的!所以您仅仅围绕三个主要的为阵地,进行重点解析,就是最理性的应对上法所在了 str…...
一起Talk Android吧(第五百一十八回:在Android中使用MQTT通信五)
文章目录 知识回顾问题描述解决过程经验分享各位看官们大家好,这一回中咱们说的例子是" 在Android中使用MQTT通信五",本章回内容与前后章节内容无关联。闲话休提,言归正转,让我们一起Talk Android吧! 知识回顾 我们在前面章回中介绍了如何使用MQTT通信,包含它…...
100种思维模型之混沌与秩序思维模型-027
人类崇尚秩序与连续性,我们习惯于我们的日常世界,它以线性方式运作,没有不连续或突跳。 为此,我们学会了期望各种过程以连续方式运行,我们的内心为了让我们更有安全感,把很多事物的结果归于秩序,…...
Java开发 - Redis初体验
前言 es我们已经在前文中有所了解,和es有相似功能的是Redis,他们都不是纯粹的数据库。两者使用场景也是存在一定的差异的,本文目的并不重点说明他们之间的差异,但会简要说明,重点还是在对Redis的了解和学习上。学完本…...
Python - 使用 pymysql 操作 MySQL 详解
目录创建连接 pymsql.connect() 方法的可传参数连接对象 conn pymsql.connect() 方法游标对象 cursor() 方法使用示例创建数据库表插入数据操作数据查询操作数据更新操作数据删除操作SQL中使用变量封装使用简单使用: import pymysqldb pymysql.connect(host,user…...
机器学习-卷积神经网络CNN中的单通道和多通道图片差异
背景 最近在使用CNN的场景中,既有单通道的图片输入需求,也有多通道的图片输入需求,因此又整理回顾了一下单通道或者多通道卷积的差别,这里记录一下探索过程。 结论 直接给出结论,单通道图片和多通道图片在经历了第一…...
考研复试——计算机组成原理
文章目录计算机组成原理1. 计算机系统由哪两部分组成?计算机系统性能取决于什么?2. 冯诺依曼机的主要特点?3. 主存储器由什么组成,各部分有什么作用?4. 什么是存储单元、存储字、存储字长、存储体?5. 计算机…...
硬件设计 之摄像头分类(IR摄像头、mono摄像头、RGB摄像头、RGB-D摄像头、鱼眼摄像头)
总结一下在机器人上常用的几种摄像头,最近在组装机器人时,傻傻分不清摄像头的种类。由于本人知识有限,以下资料都是在网上搜索而来,按照摄像头的分类整理一下,供大家参考: 1.IR摄像头: IRinfr…...
PTA:C课程设计(2)
山东大学(威海)2022级大一下C习题集(2)2-5-1 字符定位函数(程序填空题)2-5-2 判断回文(程序填空题)2-6-1 数字金字塔(函数)2-6-2 使用函数求最大公约数(函数)2-6-3 使用函数求余弦函…...
第四章:面向对象编程
第四章:面向对象编程 4.1:面向过程与面向对象 面向过程(POP)与面向对象(OOP) 二者都是一种思想,面向对象是相对于面向过程而言的。面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。面向对象&…...
Linux 安装npm yarn pnpm 命令
下载安装包 node 下载地址解压压缩包 tar -Jxf node-v19.7.0-linux-x64.tar.xz -C /root/app echo "export PATH$PATH:/app/node-v16.9.0-linux-x64" >> /etc/profile source /etc/profile ln -sf /app/node-v16.9.0-linux-x64/bin/npm /usr/local/bin/ ln -…...
linux SPI驱动代码追踪
一、Linux SPI 框架概述 linux系统下的spi驱动程序从逻辑上可以分为3个部分: SPI Core:SPI Core 是 Linux 内核用来维护和管理 spi 的核心部分,SPI Core 提供操作接口,允许一个 spi master,spi driver 和 spi device 在 SPI Cor…...
Ls-dyna材料的相关学习笔记
Elastic Linear elastic materials -Isotropic:各向同性材料 -orthotropic 正交各向异性的 -anistropic 各向异性的...
Arrays方法(copyOfRange,fill)
Arrays方法 1、Arrays.copyOfRange Arrays.copyOfRange的使用方法 功能: 将数组拷贝至另外一个数组 参数: original:第一个参数为要拷贝的数组对象 from:第二个参数为拷贝的开始位置(包含) to:…...
AcWing - 蓝桥杯集训每日一题(DAY 1——DAY 5)
文章目录一、AcWing 3956. 截断数组(中等)1. 实现思路2. 实现代码二、AcWing 3729. 改变数组元素(中等)1. 实现思路2. 实现代码三、AcWing 1460. 我在哪?(简单)1. 实现思路2. 实现代码四、AcWin…...
RHCSA-文件的其他命令(3.7)
目录 文件的其他命令: 文本内容统计wc 移动和复制(cp) 移动 查找文件的路径 压缩和解压缩 .tar(归档命令) shell-命令解释器 linux中的特殊字符 查看系统上的别名:alias 历史命令(his…...
多线程update导致的mysql死锁问题处理方法
最近想起之前处理过的一个mysql 死锁问题,是在高并发下update批量更新导致的,这里探讨一下发生的原因,以及解决办法; 发生死锁的sql语句如下,其中where条件后的字段是有复合索引的。 update t_push_message_device_h…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
