LinkedBlockingDeque 阻塞队列

LinkedBlockingQueue 链式阻塞队列的使用方法和原理 相关性文章: 了解BlockingQueue 大体框架和实现思路 并发相关文章: ReentrantLock源码 解析AQS锁加锁释放锁的实现机制 CAS算法详解 ABA问题以及解决办法 目录 概览 使用方法 源码解析 说明 队列容器 结构图 next三种情况 入队操作 出队操作 关键成员变量 初始化 put方法 put方法几个关注点 总体分析 count属性并发问题 唤醒消费者 take方法 总结 概览 1. 基于链表的可选有界阻塞队列。根据F.. 阅读详情

一、简述

LinkedBlockingDeque 是一个由链表结构组成的双向阻塞队列,即可以从队列的两端插入和移除元素。双向队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。相比于其他阻塞队列,LinkedBlockingDeque 多了 addFirst、addLast、peekFirst、peekLast 等方法。以first结尾的方法,表示插入、获取或移除双端队列的第一个元素。以 last 结尾的方法,表示插入、获取或移除双端队列的最后一个元素。LinkedBlockingDeque 是可选容量的,在初始化时可以设置容量防止其过度膨胀。如果不设置,默认容量大小为 Integer.MAX_VALUE。LinkedBlockingDeque 类有三个构造方法:

public LinkedBlockingDeque()
public LinkedBlockingDeque(int capacity)
public LinkedBlockingDeque(Collection<? extends E> c)

二、LinkedBlockingDeque 源码详解

LinkedBlockingDeque 类定义为:

public class LinkedBlockingDeque<E>
    extends AbstractQueue<E>
    implements BlockingDeque<E>, java.io.Serializable

该类继承自 AbstractQueue 抽象类,又实现了 BlockingDeque 接口。BlockingDeque 接口定义如下:

public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E>

BlockingDeque 继承自 BlockingQueue 和 Deque 接口,BlockingDeque 接口定义了在双端队列中常用的方法。

LinkedBlockingDeque 类中的数据都被封装成了 Node 对象:

 static final class Node<E> {
        E item;
        Node<E> prev;
        Node<E> next;
        Node(E x) {
            item = x;
        }
    }

LinkedBlockingDeque 类中的重要字段如下:

// 队列双向链表首节点
transient Node<E> first;
// 队列双向链表尾节点
transient Node<E> last;
// 双向链表元素个数
private transient int count;
// 双向链表最大容量
private final int capacity;
// 全局独占锁
final ReentrantLock lock = new ReentrantLock();
// 非空Condition对象
private final Condition notEmpty = lock.newCondition();
// 非满Condition对象
private final Condition notFull = lock.newCondition();

LinkedBlockingDeque 类的底层实现和 LinkedBlockingQueue 类很相似,都有一个全局独占锁,和两个 Condition 对象,用来阻塞和唤醒线程。

LinkedBlockingDeque 类对元素的操作方法比较多。针对元素的入队、出队操作以 putFirst、putLast、pollFirst、pollLast 方法来进行分析。

三、入队

1️⃣putFirst(E e) 是将指定的元素插入双端队列的开头,源码如下:

public void putFirst(E e) throws InterruptedException {
    // 若插入元素为null,则直接抛出NullPointerException异常
    if (e == null) throw new NullPointerException();
    // 将插入节点包装为Node节点
    Node<E> node = new Node<E>(e);
    // 获取全局独占锁
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        while (!linkFirst(node))
            notFull.await();
    } finally {
        // 释放全局独占锁
        lock.unlock();
    }
}

2️⃣入队操作是通过 linkFirst(E e) 来完成的,如下所示:

private boolean linkFirst(Node<E> node) {
    // assert lock.isHeldByCurrentThread();
    // 元素个数超出容量。直接返回false
    if (count >= capacity)
        return false;
    // 获取双向链表的首节点
    Node<E> f = first;
    // 将node设置为首节点
    node.next = f;
    first = node;
    // 若last为null,设置尾节点为node节点
    if (last == null)
        last = node;
    else
        // 更新原首节点的前驱节点
        f.prev = node;
    ++count;
    // 唤醒阻塞在notEmpty上的线程
    notEmpty.signal();
    return true;
}

若入队成功,则 linkFirst(E e) 返回 true,否则返回 false。若该方法返回 false,则当前线程会阻塞在 notFull 条件上。

3️⃣putLast(E e) 是将指定的元素插入到双端队列的末尾,源码如下:

public void putLast(E e) throws InterruptedException {
    // 若插入元素为null,则直接抛出NullPointerException异常
    if (e == null) throw new NullPointerException();
    // 将插入节点包装为Node节点
    Node<E> node = new Node<E>(e);
    // 获取全局独占锁
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        while (!linkLast(node))
            notFull.await();
    } finally {
        // 释放全局独占锁
        lock.unlock();
    }
}

4️⃣该方法和 putFirst(E e) 几乎一样,不同点在于,putLast(E e) 通过调用 linkLast(E e) 来插入节点:

private boolean linkLast(Node<E> node) {
    // assert lock.isHeldByCurrentThread();
    // 元素个数超出容量。直接返回false
    if (count >= capacity)
        return false;
    // 获取双向链表的尾节点
    Node<E> l = last;
    // 将node设置为尾节点
    node.prev = l;
    last = node;
    // 若first为null,设置首节点为node节点
    if (first == null)
        first = node;
    else
        // 更新原尾节点的后继节点
        l.next = node;
    ++count;
    // 唤醒阻塞在notEmpty上的线程
    notEmpty.signal();
    return true;
}

若入队成功,则 linkLast(E e) 返回 true,否则返回 false。若该方法返回 false,则当前线程会阻塞在 notFull 条件上。

四、出队

1️⃣pollFirst() 是获取并移除此双端队列的首节点,若不存在,则返回 null,源码如下:

public E pollFirst() {
    // 获取全局独占锁
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        return unlinkFirst();
    } finally {
        // 释放全局独占锁
        lock.unlock();
    }
}

2️⃣移除首节点的操作是通过 unlinkFirst() 来完成的:

private E unlinkFirst() {
    // assert lock.isHeldByCurrentThread();
    // 获取首节点
    Node<E> f = first;
    // 首节点为null,则返回null
    if (f == null)
        return null;
    // 获取首节点的后继节点
    Node<E> n = f.next;
    // 移除first,将首节点更新为n
    E item = f.item;
    f.item = null;
    f.next = f; // help GC
    first = n;
    // 移除首节点后,为空队列
    if (n == null)
        last = null;
    else
        // 将新的首节点的前驱节点设置为null
        n.prev = null;
    --count;
    // 唤醒阻塞在notFull上的线程
    notFull.signal();
    return item;
}

3️⃣pollLast() 是获取并移除此双端队列的尾节点,若不存在,则返回 null,源码如下:

public E pollLast() {
    // 获取全局独占锁
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        return unlinkLast();
    } finally {
        // 释放全局独占锁
        lock.unlock();
    }
}

4️⃣移除尾节点的操作是通过 unlinkLast() 来完成的:

private E unlinkLast() {
    // assert lock.isHeldByCurrentThread();
    // 获取尾节点
    Node<E> l = last;
    // 尾节点为null,则返回null
    if (l == null)
        return null;
    // 获取尾节点的前驱节点
    Node<E> p = l.prev;
    // 移除尾节点,将尾节点更新为p
    E item = l.item;
    l.item = null;
    l.prev = l; // help GC
    last = p;
    // 移除尾节点后,为空队列
    if (p == null)
        first = null;
    else
        // 将新的尾节点的后继节点设置为null
        p.next = null;
    --count;
    // 唤醒阻塞在notFull上的线程
    notFull.signal();
    return item;
}

其实 LinkedBlockingDeque 类的入队、出队操作都是通过 linkFirst、linkLast、unlinkFirst、unlinkLast 这几个方法来实现的,源码读起来也比较简单。

LinkedBlockingDeque 是Java中的一个线程安全的双端队列(Deque)实现,它基于链表结构实现,可以在队列的两端进行高效的元素操作。生产者线程不断将元素放入队列,而消费者线程不断从队列中取出元素,演示了阻塞操作的特性。如果指定了容量限制,则队列会在达到容量限制时阻塞生产者线程,直到队列中的元素被消费。支持双端队列操作,您可以在队列的前端(头部)和后端(尾部)插入、移除和检查元素。:将元素插入到队列的前端,如果队列已满,会阻塞等待直到队列有空间。:将元素插入到队列的后端,如果队列已满,会阻塞等待直到队列有空间。 阅读详情

相关推荐

EWF写保护功能详解:从安装到实战操作指南

本文详细介绍了EWF写保护功能的安装与实战操作指南。EWF(Enhanced Write Filter)通过重定向写入操作保护硬盘分区,特别适合需要长期稳定运行的系统场景。文章涵盖从安装准备、图形界面操作到命令行高级管理的全流程,并提供了常见问题的解决方案,帮助用户轻松掌握这一实用工具。

weixin_28710999的博客 446

阻塞队列之六:LinkedBlockingDeque

一、LinkedBlockingDeque简介   java6增加了两种容器类型,Deque和BlockingDeque,它们分别对Queue和BlockingQueue进行了扩展。  Deque是一个双端队列,deque(双端队列) 是 "Double Ended Queue" 的缩写。因此,双端队列是一个你可以从任意一端插入或者抽取元素的队列。实现了在队列头和队列尾的高效插入和移除。  Bl...

weixin_34280237的博客 384

别再手动巡检了!vRealize Operations Manager 8.x 自动化报告配置全攻略(附模板下载)

本文详细介绍了如何利用vRealize Operations Manager 8.x实现自动化巡检报告配置,大幅提升虚拟化运维效率。通过模板定制、智能调度和自动分发等功能,帮助运维团队告别手动生成报告的繁琐工作,实现90%以上的时间节省。文章还提供了实用的配置技巧和最佳实践,助力企业构建高效的自动化报告系统。

weixin_33806859的博客 297

blockingdeque java_Java并发编程之LinkedBlockingDeque阻塞队列详解

简介LinkedBlockingDeque是一个由链表结构组成的双向阻塞队列,即可以从队列的两端插入和移除元素。双向队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。相比于其他阻塞队列,LinkedBlockingDeque多了addFirst、addLast、peekFirst、peekLast等方法,以first结尾的方法,表示插入、获取获移除双端队列的第一个元素。以l...

weixin_39631953的博客 290

Python实战:5分钟搞定滑动平均窗口计算(附完整代码+逐行注释)

本文深入解析Python中滑动平均窗口计算的实现与优化,提供Numpy、Pandas等多种高效方案,并附完整代码和逐行注释。涵盖边界处理、性能优化及异常检测等实战技巧,帮助开发者快速掌握时间序列数据处理的核心技术。

weixin_30872157的博客 124

Android 13/14/15 默认授权应用权限的实现方法

Android版本修改方式实现原理13/14修改Permission.java将所有权限标记为Normal权限15修改DeviceIdleController.java + DefaultPermissionGrantPolicy.java监听应用安装并主动授权。

m0_60898338的博客 2908

双向链表的阻塞队列LinkedBlockingDeque

今天学习阻塞队列中的最后一个类LinkedBlockingDeque。 ​ LinkedBlockingDeque简介 LinkedBlockingDeque与LinkedBlockingQueue功能很相似,不过LinkedBlockingQueue底层是单向链表,LinkedBlockingDeque是双向链表。所以LinkedBlockingDeque提供了更多的以First、Last结尾的方法,可以指定从队列的头部或者尾部获取、添加数据,而LinkedBlockingQueue只能把数据加到尾部,从

IT乐知 268

Kettle实战:如何用JavaScript脚本实现数据库表批量操作(附完整代码)

本文详细介绍了如何利用Kettle的JavaScript脚本实现数据库表批量操作,包括表名采集、循环遍历和动态SQL生成等关键步骤。通过实战案例和完整代码示例,帮助ETL工程师高效处理数据密集型任务,提升数据库操作的自动化水平。

weixin_29019241的博客 231

Java并发编程之LinkedBlockingDeque阻塞队列详解

简介LinkedBlockingDeque是一个由链表结构组成的双向阻塞队列,即可以从队列的两端插入和移除元素。双向队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。相比于其他阻塞队列,LinkedBlockingDeque多了addFirst、addLast、peekFirst、peekLast等方法,以first结尾的方法,表示插入、获取获移除双端队列的第一个元素。以l...

Stay Hungry, Stay Foolish 2万+

MicroPython跨平台移植实战:从源码解析到STM32+FreeRTOS部署

本文详细解析了MicroPython的跨平台移植实战,重点介绍了如何将其从源码开始,成功部署到STM32微控制器并运行于FreeRTOS实时操作系统。内容涵盖源码结构解析、编译环境搭建、内存管理协调、FreeRTOS任务集成、数学库(math)启用与优化,以及自定义模块开发等核心步骤,为开发者提供了一套完整的、可操作的嵌入式Python移植方案。

vodka的博客 1014

科研绘图系列:R语言绘制世界地图数据分布(world map)

科研绘图系列:R语言绘制世界地图数据分布(world map)

专注生信领域 527

阻塞队列(六):LinkedBlockingDeque

阻塞队列(六):LinkedBlockingDeque 前面的BlockingQueue都是单向的FIFO队列,而LinkedBlockingDeque则是一个由链表组成的双向阻塞队列,双向队列就意味着可以从对头、对尾两端插入和移除元素,同样意味着LinkedBlockingDeque支持FIFO、FILO两种操作方式。 LinkedBlockingDeque是可选容量的,在初始化时可以设置容量防...

木村的博客 969

你的小程序地图功能还只是“摆设”吗?支付宝地图API的深度玩法都在这里了!

🏆本文收录于《滚雪球学支付宝小程序开发》专栏,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

**My Coding Family** 1817

Java阻塞队列 LinkedBlockingDeque

LinkedBlockingDeque LinkedBlockingDeque类实现了BlockingDeque接口。阅读BlockingDeque文本以获取有关的更多信息。 Deque来自“双端队列” 这个词。Deque是一个队列,你可以在插入和删除队列两端的元素。 LinkedBlockingDeque是一个Deque,如果一个线程试图从中获取一个元素,而队列空的,不管线程从哪一端试图获取元素,都会被阻塞。 以下是实例化和使用LinkedBlockingDeque的例子: BlockingDeque&l

赵彦军 1284

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

双端阻塞队列LinkedBlockingDeque源码深入解析

1 前言 与普通队列相比,阻塞队列另外支持两个附加操作,这两个附加的操作支持阻塞的插入和移除方法。 ①支持阻塞的插入方法:当队列满时,队列会阻塞插入元素的线程,直到队列不满。 ②支持阻塞的移除方法:在队列为空时,获取元素的线程会等待队列变为非空。 一般的阻塞队列相比,只能在“尾部入队、在头部出队”,而双端阻塞队列,在头部和尾部均能入队,在头部和尾部均能出队。 LinkedBlockingDeq...

小伍的程序之路 525

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

【并发编程系列8】阻塞队列之ArrayBlockingQueue,LinkedBlockingQueue,LinkedBlockingDeque原理分析

阻塞队列原理分析前言 前言 上一篇我们分析了

zwx900102的博客 2196

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Java 并发 --- 阻塞队列之LinkedBlockingDeque源码分析

LinkedBlockingDeque是基于双向链表的双端有界阻塞队列,默认使用非公平ReentrantLock实现线程安全,默认队列最大长度都为Integer.MAX_VALUE;不允许null元素添加;双端队列可以用来实现 "窃取算法" ,两头都可以操作队列,相对于单端队列可以减少一半的竞争。

小张的专栏 1807

c++输出双向队列的全部元素_阻塞队列(4)LinkedBlockingDeque源码详解

问题LinkedBlockingDeque 是什么?优缺点?应用场景?源码实现?个人启发?LinkedBlockingDeque双向并发阻塞队列。所谓双向是指可以从队列的头和尾同时操作,并发只是线程安全的实现,阻塞允许在入队出队不满足条件时挂起线程,这里说的队列是指支持FIFO/FILO实现的链表。要想支持阻塞功能,队列的容量一定是固定的,否则无法在入队的时候挂起线程。也就是capacity是fi...

weixin_36332320的博客 329

java 线程中阻塞队列的相关类(LinkedBlockingQueue、LinkedBlockingDeque、ArrayBlockingQueue等)的对比

java 线程中阻塞队列的相关类(LinkedBlockingQueue、LinkedBlockingDeque、ArrayBlockingQueue、PriorityBlockingQueue、DelayQueue、TransFerQueue),使用场景,代码示例优缺点对比,最后表格整理差异

爱的叹息的专栏 979

阻塞队列LinkedBlockingDeque与LinkedBlockingQueue(三)

一、概述:    声明:本文转载为转载文章,原出处为:Java并发学习(二十三)-LinkedBlockingQueue和LinkedBlockingDeque分析LinkedBlockingDeque是基于链表的、线程安全的双端阻塞队列。LinkedBlockingQueue是基于链表的先进先出的阻塞队列。特点:链表结构(动态数组)通过ReentrantLock实现锁利用Condition实现队...

Scott 6233

Java并发包源码学习系列:阻塞队列实现之LinkedBlockingDeque源码解析

文章目录LinkedBlockingDeque概述类图结构及重要字段linkFirstlinkLastunlinkFirstunlinkLastunlink总结参考阅读 系列传送门: Java并发包源码学习系列:AbstractQueuedSynchronizer Java并发包源码学习系列:CLH同步队列及同步资源获取与释放 Java并发包源码学习系列:AQS共享式与独占式获取与释放资源的区别 Java并发包源码学习系列:ReentrantLock可重入独占锁详解 Java并发包源码学习系列:Reent

天乔巴夏丶 762

LinkedBlockingDeque 双端阻塞队列 (deque)

LinkedBlockingDeque 是 Java 中的一个双端阻塞队列 (deque),实现了 java.util.concurrent.BlockingDeque 接口。它允许在两端进行插入和删除操作,并且这些操作可以是阻塞的,这意味着它们可以等待直到插入或删除操作成功。LinkedBlockingDeque 是一个功能强大的双端阻塞队列,适用于需要在多线程环境中以线程安全方式进行双端插入和删除操作的场景。通过理解其主要特点和常用方法,你可以在实际项目中有效地使用它来解决并发问题。

逆风飞翔 967

JDK8系列:阻塞队列 之 LinkedBlockingDeque(双向阻塞队列)源码解析

1、LinkedBlockingDeque 简介 LinkedBlockingDeque是一个基于链表的双端阻塞队列。和LinkedBlockingQueue类似,区别在于该类实现了Deque接口,而LinkedBlockingQueue实现了Queue接口。该类的继承关系如下图: 容量问题 LinkedBlockingDeque是一个可选容量的阻塞队列,如果没有设置容量,那么容量将是Int的最大值。 底层数据结构 LinkedBlockingDeque的底层数据结构是一个双端队列,该队列使用链.

啦卡的博客 522

Java阻塞队列 - LinkedBlockingDeque

LinkedBlockingDeque是Java并发包中一种基于双链表结构实现的有界阻塞队列 以下是该类的继承结构图 以下是该类的内部结构图:

简单点 275
上一篇: 延时 队列
下一篇: 反转链表(Reverse Linked List)
JFS_Study
博客等级 码龄6年 363粉丝 359原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JFS_Study

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值