ArrayBlockingQueue的take()底层原理
一、ArrayBlockingQueue 的 take() 方法的底层源码的详细介绍
ArrayBlockingQueue 是 Java 并发包 (java.util.concurrent) 中的一个基于数组实现的有界阻塞队列。它的 take() 方法是用于从队列中移除并返回队首元素的核心方法之一。当队列为空时,take() 方法会阻塞当前线程,直到队列中有新元素
1、take() 方法的功能
作用:移除并返回队列的队首元素
阻塞行为:如果队列为空,当前线程会被阻塞,直到队列中有新元素
线程安全:take() 方法是线程安全的,内部通过锁机制实现同步
2、take() 方法的源码分析
以下是 ArrayBlockingQueue 中 take() 方法的源码(基于 JDK 17):

关键点解析
1、获取锁:
使用 lock.lockInterruptibly() 获取锁,支持线程中断
如果当前线程被中断,会抛出 InterruptedException
2、检查队列是否空:
如果队列空(count == 0),调用 notEmpty.await() 使当前线程等待
notEmpty 是一个 Condition 对象,用于表示队列非空的条件
3、移除元素:
如果队列非空,调用 dequeue() 方法移除并返回队首元素
dequeue 方法会更新队列的 takeIndex 和 count,并唤醒等待 notFull 条件的生产者线程
4、释放锁:
- 在 finally 块中释放锁,确保锁一定会被释放,避免死锁
3、dequeue() 方法的源码分析
dequeue 是 take() 方法中用于实际移除元素的私有方法。以下是其源码:

关键点解析
1、获取队首元素:
从数组的 takeIndex 位置获取队首元素。
takeIndex 是下一个移除元素的位置。
2、清除队首元素:
- 将 takeIndex 位置的元素设置为 null,帮助垃圾回收。
3、更新 takeIndex:
- 如果 takeIndex 达到数组长度,将其重置为 0,实现循环数组的效果。
4、更新元素数量:
- count 表示队列中的元素数量,移除成功后递减。
5、唤醒生产者线程:
- 调用 notFull.signal() 唤醒等待 notFull 条件的生产者线程。
4、take() 方法的阻塞机制
take() 方法的阻塞行为是通过 Condition 的 await() 方法实现的。以下是其工作原理:
1、队列空时的阻塞:
如果队列空,当前线程会调用 notEmpty.await(),释放锁并进入等待状态。
线程会被加入到 notEmpty 条件的等待队列中。
2、被唤醒的条件:
当生产者线程向队列中插入一个元素时,会调用 notEmpty.signal() 或 notEmpty.signalAll(),唤醒等待 notEmpty 条件的消费者线程。
被唤醒的线程会重新尝试获取锁,并检查队列是否仍然空。
3、中断处理:
- 如果线程在等待期间被中断,await() 方法会抛出 InterruptedException,并清除中断状态
5、take() 方法的性能优化
循环数组:
ArrayBlockingQueue 使用循环数组存储元素,避免了数组的频繁扩容和数据拷贝。
通过 putIndex 和 takeIndex 实现队列的循环利用。
锁分离:
- 使用单独的 Condition 对象(notFull 和 notEmpty)分别管理生产者和消费者的等待队列,减少锁竞争。
公平性:
- 可以通过构造函数指定是否使用公平锁。公平锁会按照线程等待的顺序分配锁,避免线程饥饿。
二、总结
ArrayBlockingQueue 的 take() 方法通过以下机制实现了线程安全的阻塞移除:
1、锁机制:使用 ReentrantLock 保证线程安全。
2、条件变量:使用 notFull 和 notEmpty 管理线程的等待和唤醒。
3、循环数组:通过循环数组高效管理队列元素。
ArrayBlockingQueue的take()底层原理的更多相关文章
- Java面试底层原理
面试发现经常有些重复的面试问题,自己也应该学会记录下来,最好自己能做成笔记,在下一次面的时候说得有条不紊,深入具体,面试官想必也很开心.以下是我个人总结,请参考: HashSet底层原理:(问了大几率 ...
- Neo4j图数据库简介和底层原理
现实中很多数据都是用图来表达的,比如社交网络中人与人的关系.地图数据.或是基因信息等等.RDBMS并不适合表达这类数据,而且由于海量数据的存在,让其显得捉襟见肘.NoSQL数据库的兴起,很好地解决了海 ...
- 【T-SQL进阶】02.理解SQL查询的底层原理
本系列[T-SQL]主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础]02.联接查询 [T-SQL基础]03.子查询 [T-SQL基础]04.表表达式 ...
- spring框架的IOC的底层原理
1.IOC概念:spring容器创建对象并管理 2.IOC的底层原理的具体实现: 1)所使用的技术: (1). dom4j解析xml配置文件 (2).工厂设计模式(解耦合) (3).反射 第一步:配置 ...
- 深入研究Sphinx的底层原理和高级使用
深入研究Sphinx的底层原理和高级使用
- 深入研究Node.js的底层原理和高级使用
深入研究Node.js的底层原理和高级使用
- HashMap的底层原理
简单说: 底层原理就是采用数组加链表: 两张图片很清晰地表明存储结构: 既然是线性数组,为什么能随机存取?这里HashMap用了一个小算法,大致是这样实现: // 存储时: int hash = ke ...
- 操作系统底层原理与Python中socket解读
目录 操作系统底层原理 网络通信原理 网络基础架构 局域网与交换机/网络常见术语 OSI七层协议 TCP/IP五层模型讲解 Python中Socket模块解读 TCP协议和UDP协议 操作系统底层原理 ...
- Servlet底层原理、Servlet实现方式、Servlet生命周期
Servlet简介 Servlet定义 Servlet是一个Java应用程序,运行在服务器端,用来处理客户端请求并作出响应的程序. Servlet的特点 (1)Servlet对像,由Servlet容器 ...
- Spring Aop底层原理详解
Spring Aop底层原理详解(来源于csdn:https://blog.csdn.net/baomw)
随机推荐
- 微信小程序上拉触底事件onReachBottom不触发的解决方案
1.配置属性问题 //设置容器高度为100% page{ height: 100% } 2. 切换页面时 滚动条滚回到顶部 //切换页面时调用API wx.pageScrollTo({ scrollT ...
- 简单聊一下*SWITCH*交换机的作用
交换机 交换机工作在数据链路层的物理设备或者说是接入层的物理设备,转发数据帧. 随着企业网络的发展,越来越多的用户需要接入到网络,交换机提供的大量的接入端口能够很好地满足这种需求.同时,交换机也彻底解 ...
- Linux Bridge和Tap关系详解
本文分享自天翼云开发者社区<Linux Bridge和Tap关系详解>,作者:x****n Linux Bridge介绍 Bridge(桥)是Linux上用来做TCP/IP二层协议交换的设 ...
- Layer子域名挖掘机
Layer子域名挖掘机 Layer子域名挖掘机是一款功能强大的域名查询工具,主要用于提供网站子域名的查询服务. 域名与子域名 域名 域名,又称网域,是互联网上用于标识特定计算机或计算机组的一串由点分隔 ...
- Codeforces 319B Psychos in a Line 题解 [ 绿 ] [ 单调栈 ] [ 动态规划 ] [ adhoc ]
Psychos in a Line:很好的单调栈优化 dp 题! 观察 我们先观察,一个精神病人会一直杀到什么时候.显然,会杀到右边第一个比他大的精神病人那里,然后他就杀不动了. 因此我们可以从右往左 ...
- 用python做时间序列预测七:时间序列复杂度量化
本文介绍一种方法,帮助我们了解一个时间序列是否可以预测,或者说了解可预测能力有多强. Sample Entropy (样本熵) Sample Entropy是Approximate Entropy(近 ...
- 库卡机器人KR240电源模块维修思路讲解
一.库卡机器人KR240电源模块故障诊断 故障诊断是维修过程中的关键步骤.使用库卡提供的诊断工具或软件,对库卡机器人KR240电源模块进行故障诊断.重点关注电源供应.输出电压.电流等关键参数.通过诊断 ...
- **Selenium IDE、Selenium RC 和 WebDriver 之间有什么区别?**
- Web前端入门第 8 问:HTML <!DOCTYPE> 申明有何用处?如果没有此申明有什么问题?
HELLO,这里是大熊学习前端开发的入门笔记. 本系列笔记基于 windows 系统. 先电脑端浏览器打开任何一个网页,比如百度. 再用 ctrl + u 快捷键即可查看源码,瞅瞅第一行代码,是不是都 ...
- Mac 干净彻底地卸载 MySQL
前言 卸载MySQL,首先得知道MySQL的路径.默认的话是在/usr/local文件夹下的. 在系统偏好设置面板中可以看到之前安装的MySQL,此时若想卸载MySQL,可以按照如下步骤来. 之前安装 ...