当前位置: 首页 > news >正文

Java并发基础:LinkedBlockingDeque全面解析!

Java并发基础:LinkedBlockingDeque全面解析! - 程序员古德

内容概要

LinkedBlockingDeque提供了线程安全的双端队列实现,它支持在队列两端高效地进行插入和移除操作,同时具备阻塞功能,能够很好地协调生产者与消费者之间的速度差异,其内部基于链表结构,使得并发性能优异,是处理多线程间数据传递的理想选择。

核心概念

LinkedBlockingDeque 实现了一个线程安全的双端队列(Deque,即 double-ended queue),这个队列在两端都可以添加和移除元素,而且它是阻塞的,意味着当队列为空时,如果线程尝试从队列中取元素,线程会被阻塞,直到队列中有元素可供取出;同样地,如果队列已满,尝试添加元素的线程也会被阻塞,直到队列中有空间可供添加新元素。

举一个生活中的实际案例,比如一个面包店,面包师傅负责生产面包(生产者),顾客来店里买面包(消费者),面包师傅做好面包后,会把它们放在一个展示架上供顾客挑选;顾客则从这个展示架上取走他们想要的面包,这里使用LinkedBlockingDeque 来模拟这个场景。面包师傅(生产者线程)在队列的一端放入新做好的面包(添加元素到队列),而顾客(消费者线程)从队列的另一端取走面包(从队列中移除元素):

  1. 阻塞特性:如果展示架上没有面包(队列为空),顾客就会被阻塞,直到面包师傅做好新的面包并放到展示架上,同样,如果展示架满了(队列已满),面包师傅就会被阻塞,直到有顾客取走一些面包,腾出空间来放新的面包。
  2. 双端操作:在这个场景中,虽然通常面包师傅只在一端放面包,顾客在另一端取面包,但双端队列的灵活性意味着也可以轻松改变这个行为,比如,如果有特殊情况,面包师傅可以从展示架上取回一些面包(从队列的另一端移除元素),或者顾客可以预先把他们的面包订单放到展示架上(在队列的另一端添加元素)。

LinkedBlockingDeque 是一个线程安全的双端队列,允许从队列的两端添加和移除元素,并且它是阻塞的,他通常用来解决以下问题:

  1. 线程安全:在多线程环境中,当多个线程需要访问和修改共享数据时,LinkedBlockingDeque 提供了一种线程安全的方式来存储和检索这些数据,它内部的同步机制确保了数据的一致性和完整性。
  2. 阻塞操作:当队列为空时,消费者线程调用 take() 方法会被阻塞,直到生产者线程向队列中添加元素,同样,当队列已满时,生产者线程调用 put() 方法也会被阻塞,直到消费者线程从队列中移除元素,这种阻塞行为有助于防止线程在不必要的情况下空转或浪费CPU资源。
  3. 容量限制LinkedBlockingDeque 可以在创建时指定一个最大容量,这个容量限制了队列中可以存储的元素数量,有助于防止内存溢出,当队列达到最大容量时,生产者线程会被阻塞,直到队列中有空间可用。
  4. 双端操作:与普通的 BlockingQueue 接口实现相比,LinkedBlockingDeque 提供了双端队列的功能,允许从队列的两端添加和移除元素,这为某些特定的应用场景提供了更大的灵活性。
  5. 高效的并发性能:由于其内部使用链表数据结构,LinkedBlockingDeque 在处理大量并发操作时通常具有较好的性能,它适用于需要高吞吐量和低延迟的生产者-消费者场景。

代码案例

下面是一个简单的例子,演示了如何使用 LinkedBlockingDeque 类,如下代码:

import java.util.concurrent.BlockingQueue;  
import java.util.concurrent.LinkedBlockingDeque;  public class LinkedBlockingDequeExample {  public static void main(String[] args) throws InterruptedException {  // 创建一个容量为 5 的 LinkedBlockingDeque  BlockingQueue<String> deque = new LinkedBlockingDeque<>(5);  // 启动一个生产者线程,向队列中添加元素  Thread producer = new Thread(() -> {  try {  for (int i = 0; i < 10; i++) {  String item = "Item-" + i;  deque.put(item); // 当队列满时,该方法会阻塞  System.out.println("Produced: " + item);  Thread.sleep(200); // 模拟生产延迟  }  } catch (InterruptedException e) {  e.printStackTrace();  }  });  // 启动一个消费者线程,从队列中移除元素  Thread consumer = new Thread(() -> {  try {  for (int i = 0; i < 10; i++) {  String item = deque.take(); // 当队列空时,该方法会阻塞  System.out.println("Consumed: " + item);  Thread.sleep(300); // 模拟消费延迟  }  } catch (InterruptedException e) {  e.printStackTrace();  }  });  // 启动生产者和消费者线程  producer.start();  consumer.start();  // 等待两个线程执行完成  producer.join();  consumer.join();  System.out.println("Producer and Consumer threads have finished.");  }  
}

在上面代码中,创建了一个 LinkedBlockingDeque 实例,并指定了它的最大容量为 5,然后创建了一个生产者线程和一个消费者线程,生产者线程将循环 10 次,每次生产一个字符串并将其放入队列中,如果队列已满,put 方法将会阻塞直到队列中有空间可用,消费者线程也将循环 10 次,每次从队列中取出一个元素并打印它,如果队列为空,take 方法将会阻塞直到队列中有元素可取。

由于生产者和消费者线程的速度可能不同,LinkedBlockingDeque 作为一个阻塞队列,能够协调这两个线程之间的速度差异,确保它们可以协同工作,而不会因为队列为空或满而导致任何一方停滞不前。

核心API

LinkedBlockingDeque 实现了 BlockingDeque 接口,是一个线程安全的双端队列,以下是 LinkedBlockingDeque 类中一些主要方法的含义:

  1. add(E e)
    将指定的元素插入到此双端队列表示的队列中(即在此双端队列的尾部),如果立即可行且不会违反容量限制,则成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException,这是 Queue 接口的方法。
  2. offer(E e)
    将指定的元素插入到此双端队列表示的队列中(即在此双端队列的尾部),如果立即可行且不会违反容量限制,则成功时返回 true,如果当前没有可用的空间,则返回 false,这是 Queue 接口的方法。
  3. put(E e) throws InterruptedException
    将指定的元素插入到此双端队列表示的队列中(即在此双端队列的尾部),必要时将等待空间变得可用,这是 BlockingQueue 接口的方法。
  4. offer(E e, long timeout, TimeUnit unit)
    将指定的元素插入到此双端队列表示的队列中,必要时将等待指定的时间以使空间变得可用,这是 BlockingQueue 接口的方法。
  5. remove()
    获取并移除此双端队列表示的队列的头部,如果此双端队列为空,则抛出 NoSuchElementException,这是 Queue 接口的方法。
  6. poll()
    获取并移除此双端队列表示的队列的头部,如果此双端队列为空,则返回 null,这是 Queue 接口的方法。
  7. take() throws InterruptedException
    获取并移除此双端队列表示的队列的头部,在元素变得可用之前一直等待,这是 BlockingQueue 接口的方法。
  8. poll(long timeout, TimeUnit unit)
    获取并移除此双端队列表示的队列的头部,在指定的时间内等待元素变得可用,这是 BlockingQueue 接口的方法。
  9. peek()
    获取但不移除此双端队列表示的队列的头部,如果此双端队列为空,则返回 null,这是 Queue 接口的方法。
  10. element()
    获取但不移除此双端队列表示的队列的头部,这是 Queue 接口的方法。
  11. push(E e)
    将元素推入此双端队列表示的堆栈中(即在此双端队列的头部),如果立即可行且不会违反容量限制,则成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException
  12. pop()
    从此双端队列表示的堆栈中弹出一个元素,如果此双端队列为空,则抛出 NoSuchElementException
  13. addFirst(E e), addLast(E e)
    将指定的元素插入此双端队列的开头或结尾。
  14. offerFirst(E e), offerLast(E e)
    将指定的元素插入此双端队列的开头或结尾,如果立即可行且不会违反容量限制,则成功时返回 true,如果当前没有可用的空间,则返回 false
  15. removeFirst(), removeLast()
    获取并移除此双端队列的第一个元素或最后一个元素。
  16. pollFirst(), pollLast()
    获取并移除此双端队列的第一个元素或最后一个元素,如果此双端队列为空,则返回 null
  17. getFirst(), getLast()
    获取但不移除此双端队列的第一个元素或最后一个元素。
  18. peekFirst(), peekLast()
    获取但不移除此双端队列的第一个元素或最后一个元素,如果此双端队列为空,则返回 null

核心总结

Java并发基础:LinkedBlockingDeque全面解析! - 程序员古德

LinkedBlockingDeque类它融合了阻塞队列和双端队列的特性,其优点在于高效的并发性能和灵活的两端操作,适合在生产者-消费者场景中使用,能够很好地处理多线程间的数据共享和传递,缺点在高并发下如果队列大小设置不当,可能会导致过多的线程阻塞,影响系统整体性能,此外,由于是基于链表的实现,其内存占用可能相对较高。

关注我,每天学习互联网编程技术 - 程序员古德

END!

往期回顾

Java并发基础:LinkedBlockingDeque全面解析!

Java并发基础:LinkedTransferQueue全面解析!

Java并发基础:LinkedBlockingQueue全面解析!

Java并发基础:Deque接口和Queue接口的区别?

Spring核心基础:全面总结Spring中提供的那些基础工具类!

相关文章:

Java并发基础:LinkedBlockingDeque全面解析!

内容概要 LinkedBlockingDeque提供了线程安全的双端队列实现&#xff0c;它支持在队列两端高效地进行插入和移除操作&#xff0c;同时具备阻塞功能&#xff0c;能够很好地协调生产者与消费者之间的速度差异&#xff0c;其内部基于链表结构&#xff0c;使得并发性能优异&#x…...

Zabbix6.x配置中文界面 解决乱码问题

Zabbix6.x配置中文界面 解决乱码问题 Zabbix6.x界面无法选择中文&#xff0c;通过安装语言包解决。后面也解决了zabbix6中文方块&#xff08;乱码&#xff09;问题。 配置中文语言包 系统中默认没有携带中文语言包&#xff0c;可以通过以下命令查看 localectl list-locales #…...

next项目页面性能调优

next项目页面性能调优 一般来说性能优化可以分为加载时、运行时两部分的优化。 扩展参考链接&#xff1a; 前端性能优化 24 条建议 Webpack 4进阶–从前的日色变得慢 &#xff0c;一下午只够打一次包 Webpack 分包优化首屏加载 参考指标 FCP&#xff08;First Contentful P…...

性能评测|虚拟化和裸金属 K8s 哪个性能更好?

本文重点 整体而言&#xff0c;SKS&#xff08;虚拟机 Kubernetes&#xff09;可以达到裸金属 Kubernetes 性能的 82% – 96%&#xff0c;满足绝大部分场景下生产容器应用的性能需求。更多虚拟化与裸金属 Kubernetes 架构、特性、适用场景与性能对比&#xff0c;欢迎阅读文末电…...

【大厂AI课学习笔记】【1.6 人工智能基础知识】(1)人工智能、机器学习、深度学习之间的关系

6.1 人工智能、机器学习与深度学习的关系 必须要掌握的内容&#xff1a; 如上图&#xff1a;人工智能>机器学习>深度学习。 机器学习是人工智能的一个分支&#xff0c;该领域的主要研究对象是人工智能&#xff0c;特别是如何在经验学习中改进具体算法的性能。 深度学习…...

计算机毕业设计基于的农村蔬菜销售系统SSM

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; vue mybatis Maven mysql5.7或8.0等等组成&#xff0c;B…...

【Chrono Engine学习总结】3-地型terrain

由于Chrono的官方教程在一些细节方面解释的并不清楚&#xff0c;自己做了一些尝试&#xff0c;做学习总结。 1、关于物体材质 在介绍地型之前&#xff0c;要初步了解chrono中关于材质的一些基本概念。 首先&#xff0c;最基本的材质类是ChMaterialSurface,其进一步包括&…...

【Linux】构建模块

&#x1f525;博客主页&#xff1a;PannLZ &#x1f38b;系列专栏&#xff1a;《Linux系统之路》 &#x1f94a;不要让自己再留有遗憾&#xff0c;加油吧&#xff01; 文章目录 构建第一个模块1模块的makefile2内核树内构建3内核树外构建 构建第一个模块 可以在两个地方构建模…...

vscode远程连接失败

目录 解决方案尝试1解决方案尝试2 解决方案尝试1 最近通过vscode一直使用腾讯云的服务器作为远程开发环境&#xff0c;以前一直很好用。 直到最近重装了系统之后&#xff0c;发现vscode没法对云服务器进行连接了&#xff0c;即使在远程主机添加了本地的公钥也不行。直接报错:…...

C#系列-C#访问FTP服务器实现上传下载(8)

FTP Server是什么&#xff1f; FTP Server&#xff08;File Transfer Protocol Server&#xff09;&#xff0c;即文件传输协议服务器&#xff0c;是在互联网上提供文件存储和访问服务的计算机。它依照FTP协议提供服务&#xff0c;专门用来传输文件。 FTP Server允许不同的客…...

django中实现登录

Django中实现登录功能&#xff0c;通常涉及以下几个步骤&#xff1a; 一&#xff1a;实现步骤 1&#xff1a;创建用户模型&#xff1a;Django自带了一个用户认证系统&#xff0c;通常使用内置的User模型来管理用户。你也可以根据需要自定义用户模型。 2&#xff1a;创建登录表…...

【安卓操作系统——讲解】

安卓操作系统 安卓操作系统 安卓操作系统 安卓&#xff08;Android&#xff09;是一种基于Linux内核和其他开源软件的移动操作系统&#xff0c;主要用于触屏移动设备如智能手机和平板电脑。由Andy Rubin等人开发&#xff0c;最初的目的是创建一个先进的操作系统&#xff0c;用…...

Linux发行版全景:选择、使用和未来趋势

1. 引言 Linux操作系统的简介 Linux是一种自由和开源的操作系统内核&#xff0c;由Linus Torvalds在1991年首次发布。随着时间的发展&#xff0c;Linux已经成为世界上最流行的操作系统之一&#xff0c;广泛用于服务器、桌面电脑、移动设备以及嵌入式系统。Linux的主要特点是其…...

STM32 与 ARM 的联系

STM32 和 ARM 是两个不同的概念&#xff0c;但它们之间存在一定的联系。 STM32是一种微控制器产品&#xff0c;由意法半导体&#xff08;STMicroelectronics&#xff09;推出&#xff0c;其内核采用了 ARM Cortex-M 核。ARM 是一家英国芯片设计公司&#xff0c;专注于设计和许可…...

每日五道java面试题之java基础篇(二)

第一题. 为什么说 Java 语⾔“编译与解释并存”&#xff1f; ⾼级编程语⾔按照程序的执⾏⽅式分为编译型和解释型两种。 简单来说&#xff0c;编译型语⾔是指编译器针对特定的操作系统将源代码⼀次性翻译成可被该平台执⾏的机器码&#xff1b;解释型语⾔是指解释器对源程序逐…...

【Linux】Shell编程

Shell编程 目录 Shell编程1.shell基础1.输入重定向 & 输出重定向2.管道3.特殊字符(3.1)通配符(3.2)引号(3.3)注释符(#) 4.别名5.命令历史history 2.Shell脚本Shell脚本的执行方式(1)为脚本文件加上可执行权限,然后在命令行直接输入shell脚本文件名执行。(2)sh shell脚本名(…...

斯巴鲁Subaru EDI需求分析

斯巴鲁Subaru是日本运输集团斯巴鲁公司&#xff08;前身为富士重工&#xff09;的汽车制造部门&#xff0c;以性能而闻名&#xff0c;曾赢得 3 次世界拉力锦标赛和 10 次澳大利亚拉力锦标赛。 斯巴鲁Subaru EDI 需求分析 企业与斯巴鲁Subaru建立EDI连接&#xff0c;首先需要确…...

golang 集成sentry:PostgreSQL

本文介绍通过 pgx库集成sentry&#xff0c; pgx 特点是速度快&#xff0c;可以完全控制&#xff0c;并且支持所有 postgres 数据类型。 pgx地址&#xff1a; https://github.com/jackc/pgx 最简单的接入方式是自定义一个logger&#xff0c; 然后注入到pgx&#xff0c; 完整示…...

ubuntu20.04 安装mysql(8.x)

安装mysql命令 sudo apt-get install mysql-server安装完毕后&#xff0c;立即初始化密码 sudo mysql -u root # 初次进入终端无需密码ALTER USER rootlocalhost IDENTIFIED WITH caching_sha2_password BY yourpasswd; # 设置本地root密码设置mysql远程登录 设置远程登录账…...

ChatGPT升级至GPT-4 Turbo:性能升级同时更为经济

ChatGPT升级至GPT-4 Turbo&#xff1a;性能升级同时更为经济 随着技术的进步&#xff0c;ChatGPT迎来了其最新的迭代版本——GPT-4 Turbo。这一最新版本不仅在性能上得到了显著提升&#xff0c;而且在成本效益上也更加引人注目。 性能提升 GPT-4 Turbo带来了诸多改进&#x…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...