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

Java中阻塞队列原理、特点、适用场景

文章目录

    • 阻塞队列对比、总览
    • 阻塞队列本质思想
    • 主要队列讲解
      • ArrayBlockingQueue
      • LinkedBlockingQueue
      • SynchronousQueue
      • LinkedTransferQueue
      • PriorityBlockingQueue
      • DelayQueue
      • LinkedBlockingDeque

阻塞队列对比、总览

在这里插入图片描述

阻塞队列本质思想

阻塞队列都是线程安全的队列.
其最主要的功能就是当put元素的时候, 如果队列达到最大容量, 此时put线程可以自动阻塞,直到队列中有元素被取走.
当take元素的时候, 如果队列中元素为空, take线程会自动阻塞, 直到有元素被放入队列中.

那这个功能是怎样实现的呢?
其实最本质就是使用的Condition机制的await()和singnal(), 类似于synchronized中的wait()和notify().

当put元素时,发现队列中元素已满, 就调用await()方法, 阻塞当前线程, 而当有消费者获取元素后,不管有没有put线程被阻塞,都直接调用singnal()方法, 去尝试唤醒.这样就能达到效果.

Condition原理

Condition是要和lock配合使用的, 也就是Condition和ReentrantLock是绑定在一起的,而ReentrantLock底层实现其实是AQS.所以要想理解Condition的话,最好先理解AQS,不然可能会有云里雾里的感觉, 感兴趣的同学可以看看这篇文章

我们获取Condition对象可以使用lock.newCondition(),而这个方法实际上是会new出一个ConditionObject对象,该类是AQS的一个内部类.而AQS内部维护了一个同步队列,如果获取锁失败的话,会将线程放入该同步队列,同样的,condition内部也是使用同样的方式,其内部维护了一个等待队列

其大致原理如下:

  • 当awaitThread线程调用await方法后,会释放当前锁,挂起该线程, 将该线程加入到等待队列中

  • 当signalThread线程调用signal方法后,会将awaitThread线程从等待队列中移出,加入到同步队列中(此时没有唤醒),使awaitThread线程能够有机会获取到锁, 当signalThread线程真正释放锁之后, 处于同步队列中的awaitThread线程被唤醒,重新竞争获取锁, 然后执行剩下的代码.

主要队列讲解

ArrayBlockingQueue

ArrayBlockingQueue底层是以数组实现的有界阻塞队列.

我们讲所有阻塞队列都是线程安全的, 必然会用到锁, 它内部使用的是ReentrantLock.

那锁的是谁呢?

其实锁的就是这个数组对象, 因为数组是不可以变的, 存取元素都会操作这个数组.这样就能保证线程安全.

那数组是怎样实现队列的先进先出呢?

其实就是内部维护了两个指针, 每put一个新元素, puTIndex指针往后移一次,然后进行赋值; 取的时候就找takeIndex,取出后将该位置置为null.

这两个指针都是从左向右进行移动的, 移动到末尾会自动回到首位.
在这里插入图片描述

LinkedBlockingQueue

LinkedBlockingQueue 是用链表实现的 无界 阻塞队列.

因为是链表实现的, 所以它可以动态扩容, 初始可以指定容量.

我们想一想对于链表来说, 我们每次put, 其实都需要新new一个节点, 而take则是取原有节点, 所以它读和写是不影响的.所以它有两把锁.

存放元素和获取元素是两个不同的锁对象, 这样就足以保证线程安全.所以它其实就实现了锁分离, 读写不会相互阻塞, put和take是可以同时进行的,在并发量高的时候性能会高一些

在这里插入图片描述

在这里插入图片描述

SynchronousQueue

SynchronousQueue是Java并发包中提供的一种特殊类型的阻塞队列。它是一种没有容量的队列,每个插入操作必须等待另一个线程的相应移除操作,反之亦然。

它完成线程间数据交换是同步的, 也就是当你put一个元素就会直接被阻塞, 只有这个元素被take之后,put线程才会被唤醒.

其实如果只有一个线程put,一个线程take,那这个还是很容易实现的
但是其实我们可能有很多个线程put,很多个线程take,又要完成同步的数据交换.
这个怎么实现呢?

首先如果很多个线程put, 那这些线程都会被阻塞, 那这些线程所带的元素应该放哪呢?
所以需要一个容器, 去存储元素,并不是很多人理解的SynchronousQueue是没有存储容器的

这个容器其实就是以Node节点构成的队列, 当put元素的时候, 把put线程中携带的元素封装成Node节点,同时该节点还存储了当前put线程,也就是绑定该线程.然后将该线程阻塞. 一直阻塞到该Nodo的节点被take之后, 再唤醒put线程.从而实现同步.

在这里插入图片描述

由于SynchronousQueue需要一对线程进行插入和移除操作,因此需要额外的线程协调来保证操作的成功。如果某个线程插入元素而没有其他线程移除,或者某个线程移除元素而没有其他线程插入,那么可能会导致线程阻塞,甚至死锁。

LinkedTransferQueue

如果理解了LinkedBlockingQueue和SynchronousQueue,那LinkedTransferQueue也很好理解了.

但是它有一个很大的特点, 结合了LinkedBlockingQueue和SynchronousQueue的特点.
你可以自己控制放元素是否需要被阻塞

比如使用put方法就不会阻塞,立即返回
而使用transfer方法就会阻塞线程,等待被消费者消费

而取元素基本和SynchronousQueue一样,都会阻塞直到有新的元素可以被取出.

PriorityBlockingQueue

PriorityBlockingQueue是一个可以实现优先级任务的并发阻塞队列,它继承自BlockingQueue接口,实现了一个基于优先级的无界阻塞队列。它的特点是当多个线程同时插入元素时,会按照元素的优先级进行排序,并且可以保证在获取元素时,总是返回优先级最高的元素

那是怎样实现的呢?

它的底层数据结构是一个数组实现的平衡二叉树, 并且是一个最小堆,最小堆的特点是每个节点的值都小于或等于其子节点的值. 所以它的根节点一定是最小的值

在这里插入图片描述

而每次返回的优先级最高的元素也就是这个根节点, 当前的最小值.
当然, 每次取元素或者存元素都需要排序. 性能也会受到一定影响.

DelayQueue

DelayQueue允许将任务按照延迟时间进行排序,保证了任务按照预定的时间顺序执行。这对于需要在特定时间执行任务的场景非常有用,比如定时任务、延迟队列等。

它底层使用的是PriorityQueue, 和上面讲的PriorityBlockingQueue很类似, 只不过本身没有阻塞的功能, 阻塞功能由DelayQueue自己实现.

而PriorityQueue队列会根据元素的延迟时间自动排序。元素的延迟时间越短,它就越靠近队列头部,即优先级高. 当获取元素时, 会判断头部元素是否已经超过延迟时间, 超过则进行取出, 否则就进行阻塞.

LinkedBlockingDeque

LinkedBlockingDeque是一个基于链表的双向阻塞队列,它可以在队列的两端进行插入和删除操作.

它的实现基本和LinkedBlockingQueue类似,但是可以支持两边操作, 比如在两边同时进行插入操作.
但是也是由于这个不同点, 为了两边同时操作时的线程安全, 它存取是用的同一把锁, 这也是一个区别点.

今天的分享就到这里了,有问题可以在评论区留言,均会及时回复呀.
我是bling,未来不会太差,只要我们不要太懒就行, 咱们下期见.
在这里插入图片描述

相关文章:

Java中阻塞队列原理、特点、适用场景

文章目录 阻塞队列对比、总览阻塞队列本质思想主要队列讲解ArrayBlockingQueueLinkedBlockingQueueSynchronousQueueLinkedTransferQueuePriorityBlockingQueueDelayQueueLinkedBlockingDeque 阻塞队列对比、总览 阻塞队列本质思想 阻塞队列都是线程安全的队列. 其最主要的功能…...

PHP之linux、apache和nginx与安全优化面试题

1.linux常用命令 查看目录pwd 创建文件touch 创建目录mkdir 删除文件rm 删除目录rmdir移动改名文件 mc 查询目录find 修改权限chmod 压缩包 tar 安装 yum install 修改文件vi查看进程ps 停止进程kill 定时任务crontab 2、nginx的优化 gzip压缩优化 expires缓存…...

算法笔记:0-1背包问题

n个商品组成集合O,每个商品有两个属性vi(体积)和pi(价格),背包容量为C。 求解一个商品子集S,令 优化目标 1. 枚举所有商品组合 共2^n - 1种情况 2. 递归求解 KnapsackSR(h, i, c)&#xff…...

C++入门-day02

引言:在上一节中我们接触了C中的命名空间,学会了C中的标准输出流。这一节,我标题一们讲讲缺省、重载。 一、缺省参数 在C中,给函数的形参默认给一个值就是缺省参数,你可能会比较懵逼,下面看一段代码。 正常…...

模板方法模式,基于继承实现的简单的设计模式(设计模式与开发实践 P11)

文章目录 实现举例应用钩子 Hook 模板方法模式是一种基于继承的设计模式,由两部分构成: 抽象父类(一般封装了子类的算法框架)具体的实现子类 实现 简单地通过继承就可以实现 举例 足球赛 和 篮球赛 都有 3 个步骤&#xff0c…...

php实战案例记录(16)php://input输入流

php://input是PHP中的一个特殊的输入流,它允许访问请求的原始数据。它主要用于处理非表单的POST请求,例如当请求的内容类型为application/json或application/xml时。使用php://input可以获取到POST请求中的原始数据,无论数据是什么格式。使用…...

cad图纸如何防止盗图(一个的制造设计型企业如何保护设计图纸文件)

在现代企业中,设计图纸是公司的重要知识产权,关系到公司的核心竞争力。然而,随着技术的发展,员工获取和传播设计图纸的途径越来越多样化,如何有效地防止员工复制设计图纸成为了企业管理的一大挑战。本文将从技术、管理…...

Windows11 安全中心页面不可用问题(无法打开病毒和威胁防护)解决方案汇总(图文介绍版)

本文目录 Windows版本与报错信息问题详细图片: 解决方案:方案一、管理员权限(若你确定你的电脑只有你一个账户,则此教程无效,若你也不清楚,请阅读后再做打算)方案二、修改注册表(常用方案)方案三、进入开发…...

1329: 【C2】【排序】奖学金

题目描述 某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序&#xff0c…...

解决dockerfile创建镜像时pip install报错的bug

项目场景: 使用docker-compose创建django容器 问题描述 > [5/5] RUN /bin/bash -c source ~/.bashrc && python3 -m pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple: 0.954 Looking in indexes: https://…...

算法题:分发饼干

这个题目是贪心算法的基础练习题,解决思路是排序双指针谈心法,先将两个数组分别排序,优先满足最小胃口的孩子。(本题完整题目附在了最后面) 代码如下: class Solution(object):def findContentChildren(se…...

WebSocket编程golang

WebSocket编程 WebSocket协议解读 websocket和http协议的关联: 都是应用层协议,都基于tcp传输协议。跟http有良好的兼容性,ws和http的默认端口都是80,wss和https的默认端口都是443。websocket在握手阶段采用http发送数据。 we…...

PHP之redis 和 memache面试题

目录 1、什么是Redis?它的主要特点是什么? 2、redis数据类型 3、Redis的持久化机制有哪些?它们之间有什么区别? 4、Redis的主从复制是什么?如何配置Redis的主从复制? 5、Redis的集群模式是什么&#xf…...

java socket实现代理Android App

实现逻辑就是转发请求和响应。 核心代码 // 启动代理服务器private void startProxyServer() {new Thread(new ProxyServer()).start();}// 代理服务器static class ProxyServer implements Runnable {Overridepublic void run() {try {// 监听指定的端口int port 8098; //一…...

Nacos与Eureka的区别

大家好我是苏麟今天说一说Nacos与Eureka的区别. Nacos Nacos的服务实例分为两种l类型: 临时实例:如果实例宕机超过一定时间,会从服务列表剔除,默认的类型。非临时实例:如果实例宕机,不会从服务列表剔除&…...

浅谈Rob Pike的五条编程规范

又是一篇需要我们多些思考的文章~ 简介下Rob Pike Rob Pike是Unix的先驱,UTF-8的设计人,Go语言核心设计者之一。 Rob Pike的5条编程规则 原文地址:http://users.ece.utexas.edu/~adnan/pike.html 中文翻译: 罗布派克&#x…...

LeetCode 377.组合总和IV 可解决一步爬m个台阶到n阶楼顶问题( 完全背包 + 排列数)

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围 示例 1: 输入:nums [1,2,3], target 4 输出:7 解释&#x…...

C中volatile总结

在CPU处理过程中,需要将内存中的数据载入到寄存器中才能计算,所以可能涉及到一个问题,如果内存中的数据被更改了,但是寄存器还是使用的旧数据,这样就会造成数据的不同步。 一、volatile关键字的作用 使用volatile关键…...

asp.net班级管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net班级管理系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c#语言开发 asp.net班级管理系统 二、功能介绍 1…...

【Pytorch笔记】6.Transforms

pytorch官方文档 - transforms transforms需要使用计算机视觉工具包:torchvision。 torchvision.transforms:常用的图像预处理方法; torchvision.datasets:常用数据集的dataset实现,如MNIST、CIFAR-10、ImageNet等&am…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...