[java基础-集合篇]LinkedBlockingQueue源码解析

news2025/1/16 9:09:49

关联较强的上一篇:
[java基础-集合篇]有界阻塞队列ArrayBlockingQueue源码解析-CSDN博客

总的来说。LinkedBlockingQueue 是一个基于链表节点的自定大小的线程安全的阻塞队列。遵循FIFO,结构上一端进一端出的单向队列。

源码注释
翻译
An optionally-bounded blocking queue based on linked nodes. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue. Linked queues typically have higher throughput than array-based queues but less predictable performance in most concurrent applications.
The optional capacity bound constructor argument serves as a way to prevent excessive queue expansion. The capacity, if unspecified, is equal to Integer.MAX_VALUE. Linked nodes are dynamically created upon each insertion unless this would bring the queue above capacity.
This class and its iterator implement all of the optional methods of the Collection and Iterator interfaces.
This class is a member of the Java Collections Framework.
基于链接节点的可选有界 阻塞队列 。此队列对元素 FIFO (先进先出) 进行排序。队列的 头部 是在队列中停留时间最长的元素。队列的 尾 部是在队列中时间最短的元素。新元素入到队列的尾部,队列检索操作在队列的头部获取元素。链接队列通常比基于阵列的队列具有更高的吞吐量,但在大多数并发应用程序中,性能的可预测性较差。
可选的 capacity bound constructor 参数用作防止过度队列扩展的一种方式。如果未指定,则 capacity 等于 Integer.MAX_VALUE。链接节点在每次插入时动态创建,除非这会使队列超过容量。
这个类及其迭代器实现了 and Iterator 接口的所有Collection可选方法。
此类是 Java Collections Framework 的成员
A variant of the "two lock queue" algorithm. The putLock gates
entry to put (and offer), and has an associated condition for
waiting puts. Similarly for the takeLock. The "count" field
that they both rely on is maintained as an atomic to avoid
needing to get both locks in most cases. Also, to minimize need
for puts to get takeLock and vice-versa, cascading notifies are
used. When a put notices that it has enabled at least one take,
it signals taker. That taker in turn signals others if more
items have been entered since the signal. And symmetrically for
takes signalling puts. Operations such as remove(Object) and
iterators acquire both locks.
Visibility between writers and readers is provided as follows:
Whenever an element is enqueued, the putLock is acquired and
count updated. A subsequent reader guarantees visibility to the
enqueued Node by either acquiring the putLock (via fullyLock)
or by acquiring the takeLock, and then reading n = count.get();
this gives visibility to the first n items.
To implement weakly consistent iterators, it appears we need to
keep all Nodes GC-reachable from a predecessor dequeued Node.
That would cause two problems:
  • allow a rogue Iterator to cause unbounded memory retention
  • cause cross-generational linking of old Nodes to new Nodes if
这是“双锁队列”算法的一个变体。putLock控制进入put(和offer)方法,并有一个关联的条件用于等待put操作。
takeLock同样如此。
它们都依赖的“count”字段被维护为原子操作,以避免在大多数情况下需要获取两个锁。
此外,为了最小化put操作需要获取takeLock以及反之亦然的需求,这里使用了级联通知。
当一个put操作发现它至少使得一个take操作成为可能时,它会向取者发送信号。
如果自信号发出以来有更多元素加入,则该取者进而会向其他取者发送信号。
对put操作向take操作发送信号的情况也是类似的处理方式。
诸如remove(Object)和迭代器的操作需要同时获取这两个锁。
写入者和读者之间的可见性通过以下方式提供:
每当一个元素被入队时,就会获取putLock并更新count。
随后的读者通过要么获取putLock(通过fullyLock方法)要么获取takeLock然后读取n = count.get()来保证能看到入队节点的可见性;这使得前n个项是可见的。
为了实现弱一致性的迭代器,看起来我们需要保持所有节点从一个被移除的前置节点GC可达。这会导致两个问题:
  • 允许一个不正常的迭代器导致无界内存保留
  • 如果旧节点链接到新节点,将导致跨代连接的问题
这种设计确保了高并发性能,同时也考虑到了内存管理和垃圾回收的影响,旨在减少不必要的内存占用,并避免由于对象引用跨越不同的垃圾回收代而导致的复杂性。此外,它还讨论了如何通过最小化获取锁的需求和利用级联通知来优化性能。对于迭代器,文中提到了维持弱一致性所带来的挑战,特别是与垃圾收集相关的方面。

LinkedBlockingQueue特点


和ArrayBlockingQueue一样,Linked标识着其链表的实现。其他LinkedBlockingQueue主要特点如下:

双锁队列(非公平锁)

较于ArrayBlockingQueue,LinkedBlockingQueue的 ReentrantLock有两个—— takeLock putLock ,因此,较于ArrayBlockingQueue的一个锁读写互斥,LinkedBlockingQueue两个锁独立工作,支持同时读写,可以减少锁竞争,提高多线程环境下性能。
LinkedBlockingQueue与ArrayBlockingQueue的 ReentrantLock都是默认构造的非公平锁NonfairSync,意味着它不会严格按照线程请求的顺序来分配资源。

可定大小边界的单向链表

较于ArrayBlockingQueue数组大小固定,LinkedBlockingQueue大小也是固定的,默认大小为Integer.MAX_VALUE。
且通过count与 capacity属性控制大小界限。

生产者消费者模型

LinkedBlockingQueue 为生产者和消费者提供了不同的阻塞策略。当队列为空时,从队列中取元素的线程(消费者)将被阻塞;当队列满时,向队列中添加元素的线程(生产者)将被阻塞。

LinkedBlockingQueue结构与属性

其中头节点item=null是构造时指定的

LinkedBlockingQueue核心方法

put-添加元素(阻塞)

在此队列的尾部插入指定的元素,必要时等待空间可用
如果之前是空的,现在队列put进元素,通知等待线程继续操作

offer方法

较put方法增加等待时间

take-获取元素(阻塞)

检索并删除此队列的头部,必要时等待,直到元素可用
dequeue最终效果:将head的下一个元素item返回。head本身回收,head的下一个元素变为head
如果之前队列是满的,现在take一个了,通知之前的等待的继续操作

遍历

以contains方法距离,看一下LinkedBlockingQueue中遍历是怎么做的

remove移除

需要注意的是,unlink更改了next,但是p.next本身没有发生变化。这样做可以确保遍历该节点的迭代器能够维持其弱一致性保证。
当没有其他节点引用p的时候, p 变成不可达对象,即会在合适的时候被回收。
LinkedBlockingQueue理论上应该不会有这种情况

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从论文到实践:Stable Diffusion模型一键生成高质量AI绘画

🏡作者主页:点击! 🤖编程探索专栏:点击! ⏰️创作时间:2024年12月24日10点02分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 AI绘画一键生成美图-变成画家 本地部…

业务幂等性技术架构体系之消息幂等深入剖析

在系统中当使用消息队列时,无论做哪种技术选型,有很多问题是无论如何也不能忽视的,如:消息必达、消息幂等等。本文以典型的RabbitMQ为例,讲解如何保证消息幂等的可实施解决方案,其他MQ选型均可参考。 一、…

【2024年华为OD机试】 (B卷,100分)- 跳房子I(Java JS PythonC/C++)

一、问题描述 题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏。 游戏参与者需要分多个回合按顺序跳到第1格直到房子的最后一格。 跳房子的过程中,可以向前跳,也可以向后跳。 假设房子的总格数是count,小红每…

鸿蒙打包发布

HarmonyOS应用/元服务发布(打包发布) https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/ide-publish-app-V13?catalogVersionV13 密钥:包含非对称加密中使用的公钥和私钥,存储在密钥库文件中,格式…

JAVA:在IDEA引入本地jar包的方法(不读取maven目录jar包)

问题: 有时maven使用的jar包版本是最新版,但项目需要的是旧版本,每次重新install会自动将mavan的jar包覆盖到项目的lib目录中,导致项目报错。 解决: 在IDEA中手动配置该jar包对应的目录。 点击菜单File->Projec…

Mac上安装Label Studio

在Mac上安装Anaconda并随后安装Label Studio,可以按照以下步骤进行: 1. 在Mac上安装Anaconda 首先,你需要从Anaconda的官方网站下载适用于Mac的安装程序。访问Anaconda官网,点击“Download Anaconda”按钮,选择适合M…

docker-compose和docker仓库

一、docker-compose 1.概述 docker-compose是一个自动编排工具,可以根据dockerfile自动化部署docker容器。 主要功能 配置定义 使用YAML文件(通常命名为docker - compose.yml)来描述应用程序的服务、网络和卷等配置。 容器编排 可以同时…

了解linux中的“of_property_read_u32()”

of_property_read_u32(node, "post-pwm-on-delay-ms",&data->post_pwm_on_delay); /*根据"post-pwm-on-delay-ms",从属性中查找并读取一个32位整数*/ /*读到一个32位整数,保存到data->post_pwm_on_delay中*/ of_property_read_u32…

nodejs 037: 前端新手教程使用引导库 Intro.js

Intro.js简介 Intro.js 是一个流行的引导库,用于提供步进式的新手教程。它可以帮助你创建用户引导,展示一些步骤和提示,逐步引导用户了解应用程序的功能。 安装方法: npm install intro.js使用方法: import introJ…

Vue篇-07

Vue UI组件库 一、移动端常用的UI组件库 1.1、Vant 1.2、Cube UI 1.3、Mint UI 二、PC端常用的UI组件库 2.1、Element UI Element - The worlds most popular Vue UI framework 安装: 按需引入: 135_尚硅谷Vue技术_element-ui按需引入_哔哩哔哩_b…

适配器模式案例

如果在这样的结构中 我们在Controller中注入,但我们后续需要修改Oss时,比如从minioService改成AliyunService时,需要改动的代码很多。于是我们抽象出一个FileService,让controller只跟fileservice耦合,这样我没只需要在…

鸿蒙UI开发——键盘弹出避让模式设置

1、概 述 我们在鸿蒙开发时,不免会遇到用户输入场景,当用户准备输入时,会涉及到输入法的弹出,我们的界面针对输入法的弹出有两种避让模式:上抬模式、压缩模式。 下面针对输入法的两种避让模式的设置做简单介绍。 2、…

Vue2+OpenLayers实现折线绘制功能(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、代码实现 3.1、初始变量 3.2、画一条折线 3.3、完整代码 四、Gitee源码 一、案例截图 二、安装OpenLayers库 npm install ol 三、代码实现 3.1、初始变量 关键代码: data() {return {map:null,// 定义路径坐…

栈算法篇——LIFO后进先出,数据与思想的层叠乐章(上)

文章目录 前言第一章:栈的基础知识回顾1.1 栈的结构与实现1.2 栈的应用第二章:删除字符串中的所有相邻重复项2.1 题目链接:https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/description/2.2 题目分析:2.3…

计算机的错误计算(二百一十二)

摘要 利用两个大模型计算 实验表明,两个大模型均进行了中肯的分析。另外,其中一个大模型给出了 Python代码,运行后,结果中有7位错误数字;而一个大模型进行加减运算时出错。 例1. 计算 下面是与一个大模型的对话…

VMware虚拟机安装Home Assistant智能家居平台并实现远程访问保姆级教程

目录 前言 1. 安装Home Assistant 前言 本文主要介绍如何在windows 10 上用VMware Workstation 17 Pro搭建 Home Assistant OS Host os version:Windows 10 Pro, 64-bit (Build 19045.5247) 10.0.19045 VMware version:VMware Workstation 17 Pro 1. 安装Home …

HarmonyOS 鸿蒙 ArkTs(5.0.1 13)实现Scroll下拉到顶刷新/上拉触底加载,Scroll滚动到顶部

HarmonyOS 鸿蒙 ArkTs(5.0.1 13)实现Scroll下拉到顶刷新/上拉触底加载 效果展示 使用方法 import LoadingText from "../components/LoadingText" import PageToRefresh from "../components/PageToRefresh" import FooterBar from "../components/…

【开源免费】基于Vue和SpringBoot的欢迪迈手机商城(附论文)

本文项目编号 T 141 ,文末自助获取源码 \color{red}{T141,文末自助获取源码} T141,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

Cyber Security 101-Offensive Security-SQLMap: The Basics(sqlmap基础)

了解 SQL 注入并通过 SQLMap 工具利用此漏洞。 任务1:介绍 SQL 注入是一个普遍存在的漏洞,长期以来一直是热门 网络安全主题。要了解这个漏洞,我们必须首先 了解什么是数据库以及网站如何与数据库交互。 数据库是可以存储、修改和 检索。它…

【数据结构-堆】力扣1792. 最大平均通过率

一所学校里有一些班级,每个班级里有一些学生,现在每个班都会进行一场期末考试。给你一个二维数组 classes ,其中 classes[i] [passi, totali] ,表示你提前知道了第 i 个班级总共有 totali 个学生,其中只有 passi 个学…