ArrayBlockingQueue的take()底层原理

news/2025/2/19 0:55:04/文章来源:https://www.cnblogs.com/jock766/p/18723203

一、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、循环数组:通过循环数组高效管理队列元素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/886407.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【CodeForces训练记录】Educational Codeforces Round 174 (Rated for Div. 2)

训练情况赛后反思 被英语读题背刺了,原来 C 题里面的 an element 不是 exacly one element 的意思,是 at least one element,读错题被一直硬控,这题没做出来的死因是高中组合数学。 A题 我们手玩样例可以发现 101 的情况必定不合法,abcd,第一个1说明abc相等,第三个1说明…

关于ENSP中 防火墙USG6000V 配置了双机热备后重启发现接口的VRRP状态变成Initialize状态的故障分析

一、故障现象:开启一个大型的配置正常的ENSP拓扑时,发现两台防火墙(主备)的接口vrrp状态都一直是Initialize状态,无法切换到master或者backup状态,或者部分接口正常。(测试发现,该故障在高配置的电脑上不是必然发生) 具体故障截图如下(vrrp状态会一直卡着初始状态,不…

关于ENSP中USG6000V重启后VRRP状态变成Initialize

一、故障现象:开启一个大型的配置正常的ENSP拓扑时,发现两台防火墙(主备)的接口vrrp状态都一直是Initialize状态,无法切换到master或者backup状态,或者部分接口正常。(测试发现,该故障在高配置的电脑上不是必然发生) 具体故障截图如下(vrrp状态会一直卡着初始状态,不…

Transformer——CNN和RNN的颠覆者?【论文精读随笔】

transformer是一种基于自注意力机制的深度神经网络模型,通过并行处理和长距离依赖捕捉,显著提升序列建模效率。其多头注意力设计增强特征提取能力,位置编码保留序列顺序信息。在机器翻译、NLP等领域表现卓越,并广泛扩展至视觉、语音等多模态任务。一、技术背景 RNN的困境与…

ArrayBlockingQueue的put方法底层原理

一、ArrayBlockingQueue的put方法底层原理 ArrayBlockingQueue 是 Java 并发包 (java.util.concurrent) 中的一个基于数组实现的有界阻塞队列。它的 put 方法是用于向队列中插入元素的核心方法之一。当队列满时,put 方法会阻塞当前线程,直到队列有空闲空间 1、put 方法的功能…

初始工程的排错

如图的错误如何排掉呢:看如下步骤截图 step1: 在idea的初始界面的右上角点击齿轮图标,然后点击"Project Structure",然后看到如下图:两个下拉框都选择jdk17,然后点击“ok” step2: 然后点击“settings”,找到“Build, Execution, Deployment”,然后点击“Bu…

黑马点评3:基于Redis实现共享session登录

在之前基础上,登录流程的变化:保存用户信息数据类型:最终:修改代码: 1. 发送验证码:src/main/java/com/hmdp/service/impl/UserServiceImpl.java@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Resource…

这份DeepSeek免费资源清单请收好(手慢无)

你是不是也遇到过这样的困境👇 👉 和Deepseek对话遇到“服务器繁忙,请稍候再试” 👉 动不动Deepseek App无响应,一堆Prompt白写 👉 想用第三方Deepseek却被告知"额度已用尽" 今天偷偷告诉你:大厂早就接入了DeepSeek满血版,免费羊毛速来!(建议先收藏再阅…

西电校园网通过PPPoE方式单线多拨

西电校园网通过PPPoE单线多拨的方式实现带宽的叠加,实现总带宽的有效利用。前言 西电的收费校园网现阶段(2025.2)执行的设备管控策略如下:一个账号可同时在线 6 台设备。 限速仅针对单设备,最高速率为 200M。针对这种设备数限制宽松的管控策略,一个非常自然的想法就是可以…

PyTorch入门--手写数字识别项目

概述 本文整理自BiliBli的《孔工码字》, 这是一个很好的视频号。讲的非常好,整理在这里,自己学习 他的Gitee地址:https://gitee.com/kongfanhe 本文通过手写数字识别项目来学习如何搭建训练神经网络。 PyTorch框架 在这个项目里,我们使用PyTorch框架,它是由Facebook开发的…

vscode+continue+ollama+deepseek-r1 实现AI代码自动补全

准备 下载: vscode: https://code.visualstudio.com/download continue( vscode 插件): https://marketplace.visualstudio.com/items?itemName=Continue.continue ollama: https://ollama.com/download deepseekR1: https://ollama.com/library/deepseek-r1 (通过 ollama…

空调

计算温度差值 首先,计算每头牛所在牛栏的理想温度 pi 和实际温度 ti 的差值 di = pi - ti,得到一个差值数组 d。我们的目标就是通过对连续区间的操作,将这个差值数组的所有元素都变为 0。 利用差分的性质 差分是一种用于记录区间变化的方法。对于一个数组 a,它的差分数组 b…