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)
随机推荐
- 深入理解第三范式(3NF):数据库设计中的重要性与实践
title: 深入理解第三范式(3NF):数据库设计中的重要性与实践 date: 2025/1/17 updated: 2025/1/17 author: cmdragon excerpt: 在数据库 ...
- Docker实践:创建并运行一个自定义的Docker Image
1 目标: 创建一个自定义的Image,在该Image中,包含一个自己的Python程序,通过docker运行该Image 容器,并执行我们自己的Python程序,通过添加数据卷,在本机能够查看Pyt ...
- 「CF1101F」Trucks and Cities
题意描述 有 \(N\) 座城市,第 \(i\) 座坐标为 \(a_i\) ,有 \(M\) 辆卡车,第 \(i\) 辆卡车要从城市 \(s_i\) 前往城市 \(e_i\) ,每单位长度耗油量为 \ ...
- 深入理解Java泛型、协变逆变、泛型通配符、自限定
禁止转载 重写了之前博客写的泛型相关内容,全部整合到这一篇文章里了,把坑都填了,后续不再纠结这些问题了.本文深度总结了函数式思想.泛型对在Java中的应用,解答了许多比较难的问题. 纯函数 协变 逆变 ...
- Q:如何实现notepad++列编辑模式
列编辑: txt编辑器大家都非常熟悉,当需要修改多行的时候只能一行一行的修改.而notepad 可以同时修改多行的数据. 1.鼠标移动光标到要选择的列 2.按住 alt 键,从上到下选择多列,光标会变 ...
- 阿里oos使用
阿里oss控制台安装 wget http://gosspublic.alicdn.com/ossutil/1.6.17/ossutil64 chmod 755 ossutil64 添加环境变量 cp ...
- FLink处理函数ProcessFunction、KeyedProcessFunction、ProcessWindowFunction、 ProcessAllWindowFunction
一.处理函数简介 在底层,我们可以不定义任何具体的算子(比如 map,filter,或者 window),而只是提炼出一个统一的"处理"(process)操作--它是所有转换算子的 ...
- pytest自动化测试 - 我对测试用例超时处理的一点看法
1 pytest自动化测试 - 我对测试用例超时处理的一点看法 1.1 背景 用例在执行过程中,可能由于网络等待,或者等待一些特殊的文件,而又由于一些异常,导致这些条件一直不能满足,用例卡死,这种 ...
- LCD显示器的接口协议
简介LCD的接口有多种,常用的LCD的连接方式有如下几种:MCU(MPU)模式,RGB模式,SPI模式,VSYNC模式,MDDI模式,DSI模式,MIPI模式,LVDS模式,TTL模式,EDP模式. ...
- Typecho博客优化,利用MyUpload进行图片压缩
写博客时,如果不压缩图片,既比较费主机存储空间,还会非常拖慢页面加载速度,特别是对于带宽小的主机.可是,如果要压缩好图片后再上传又比较麻烦,放到对象存储上还另外要钱.于是乎,就撸了这个插件,在上传时自 ...