阻塞队列-单锁实现

使用阻塞队列  

当我们多个线程下 对 一个队列进行操作,队列满了的情况下,其他线程再次 offer,会一直阻塞等待

对一个队列进行出队操作的时候,队列空的情况下,会一直阻塞等待删除,直到队列有元素的时候,会执行删除操作

一直阻塞等待的时候用自旋锁来进行等待

代码如下

阻塞队列接口

public interface BlockingQueue <E>{void offer(E e) throws InterruptedException;Boolean offer(E e,long timeout) throws InterruptedException;E poll() throws InterruptedException;
}

阻塞队列实现


public class ArrayBlockingQueue<E> implements BlockingQueue<E> {private final E[] array;private int head;//记录出队时候的头指针private int tail;//记录入队的指针private int size;//记录数组 个数private ReentrantLock lock = new ReentrantLock();private Condition headWait = lock.newCondition();//控制 入队的 同步队列private Condition tailWait = lock.newCondition();//控制出队的同步队列public ArrayBlockingQueue(int capacity) {array = (E[]) new Object[capacity];}private Boolean isFull() {return size == array.length;}private Boolean isEmpty() {return size == 0;}@Overridepublic String toString() {return "ArrayBlockingQueue{" +"array=" + Arrays.toString(array) +'}';}/*** @param e* @throws InterruptedException 在判断是否满的时候 用while循环而不是 if 为了防止虚假唤醒*/@Overridepublic void offer(E e) throws InterruptedException {lock.lockInterruptibly();try {while (isFull()) {tailWait.await();//如果满了 就让线程加入 同步队列// 一直等待被唤醒 使用while防止 多线程下的虚假唤醒}array[tail] = e;if (++tail == array.length) {tail = 0;}size++;//唤醒 出队的线程是为了 防止  在一个空队列中,删除元素的线程会一直线程等待,我们唤醒该线程//提示他可以删除headWait.signal();} finally {lock.unlock();}}/*** @param e* @param timeout* @return {@code Boolean }* @throws InterruptedException 根据 自己传入的时间   设置 入队最多等待的时间 如果*                              入队超时    那么返回false 并且该线程不会再等待唤醒*                              跟单独使用awaitNanos方法是不一样的*                               单独使用 .awaitNanos 方法  当设置的等待时间到期,线程自动启动来竞争锁*                               ,竞争不到 会到等待队列中去等待被唤醒*/@Overridepublic Boolean offer(E e, long timeout) throws InterruptedException {lock.lockInterruptibly();//把传入的毫秒 转换成纳秒long nanos = TimeUnit.MILLISECONDS.toNanos(timeout);try {while (isFull()) {if (nanos < 0) {//发现等待的时间 <0 表明超过了自己等待的时间 插入操作入队return false;}nanos = tailWait.awaitNanos(nanos);}array[tail] = e;if (++tail == array.length) {tail = 0;}size++;//唤醒 出队的线程是为了 防止  在一个空队列中,删除元素的线程会一直线程等待,我们唤醒该线程//提示他可以删除headWait.signal();return true;} finally {lock.unlock();}}@Overridepublic E poll() throws InterruptedException {lock.lockInterruptibly();try {while (isEmpty()) {headWait.await();}E e = array[head];array[head] = null;if (++head == array.length) {head = 0;}size--;tailWait.signal();//因为 我们 入队 满了的话线程等待// 删除成功之后 队列不满,唤醒入队线程return e;} finally {lock.unlock();}}
}

测试实现

public class ArrayBlockingQueueTest {public static void main(String[] args) throws InterruptedException {ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<String>(3);new Thread(new Runnable() {@Overridepublic void run() {try {blockingQueue.offer("任务2");blockingQueue.offer("任务3");blockingQueue.offer("任务4");System.out.println(blockingQueue.offer("任务1", 1000));} catch (InterruptedException e) {throw new RuntimeException(e);}}},"线程1").start();
Thread.sleep(2000);System.out.println(blockingQueue.toString());}

注意事项

我们只需要注意 condition的awaitnanos 方法,我们等待的时间一到,该线程自动唤醒争抢锁

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

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

相关文章

C++刷怪笼(2)类和对象的探索-上

1.前言 了解完C的一些入门干货之后&#xff0c;我们来对C的第一个重点就行学习——那就是类和对象&#xff0c;该重点我们分为三篇文章进行学习&#xff0c;请大家跟紧我的脚步&#xff0c;认真学知识哦~ 2.正文——类和对象 2.1类的定义 2.2.1类的定义格式 • class为定义…

echarts遍历区域折线图,单线和多线

// 单线折线图drawonelineCharts(){var echarts require("echarts");var lineCharts document.getElementsByClassName(lineChart); // 对应地使用ByClassNamethis.linecolor[#01FFD4,#1C70DD,#01FFD4,#1C70DD,#01FFD4,#1C70DD]for(var i 0;i < lineCharts.len…

内核头文件, makfile 传参

1 内核头文件&#xff0c;主要指的是&#xff0c; 在板卡上的系统上直接 &#xff0c;编译驱动模块&#xff0c;而不是在虚拟机的内核源码中 去编译内核模块。 2 makefile 传参 &#xff0c;指的是&#xff0c; 内核模块使用 makfile 定义的宏定义。 首先是 关于 在普通的makef…

ubuntu24安装cuda和cudnn

一、安装cuda 确保显卡驱动正确安装 终端输入&#xff1a; nvidia-smi显示下面结果&#xff0c;说明显卡驱动安装正常&#xff0c;可以进行下一步 1.去官网下载CUDA&#xff0c;需要注册账号下载 https://developer.nvidia.com/cuda-toolkit-archive由于我们显卡支持12.2&…

网络通信特刊合集(二)——CMC特刊推荐

特刊征稿 01 特刊名称&#xff1a; Security and Privacy for Blockchain-empowered Internet of Things 截止时间&#xff1a; 提交截止日期 2024 年 10 月 30 日 目标及范围&#xff1a; 本期特刊旨在探讨最近的进展&#xff0c;以解决在区块链授权的物联网中与安全和…

一文带你深度了解FreeRTOS——计数型信号量

本文记录FreeRTOS的计数型信号量知识&#xff0c;希望我的分享对你有所帮助&#xff01; 目录 一、计数型信号量简介 二、创建计数型信号量 1、动态创建计数型信号量 2、静态创建计数型信号量 三、结语 一、计数型信号量简介 计数型信号量在FreeRTOS中用于管理对共享资…

拥有这些AI绘画网站,让你轻松告别手绘时代!

在这个充满无限可能的数字世界里&#xff0c;AI 绘画动漫网站已经成为了许多艺术家和设计师的新宠。从手绘时代的岁月如歌&#xff0c;到今天科技的飞速发展&#xff0c;我们已经可以用AI技术创作出令人惊叹的艺术作品&#xff0c;打开了全新的创作空间。接下来&#xff0c;就让…

如何打造一个智能化的远程在线考试系统?

远程教育与在线考试已成为提升知识传播效率和学习灵活性的重要手段。 土著刷题在线考试系统&#xff0c;凭借其完善的多功能考试模块&#xff0c;为教育机构、学校乃至企业提供了一个智能化的远程在线考试解决方案。 接下来将介绍土著刷题在线考试系统如何助力用户构建一个高效…

小琳Python课堂:Python 高并发实现的基本原理(简化版)

大家好&#xff0c;这里是小琳Python课堂&#xff01; 今天&#xff0c;我们来聊聊Python中实现高并发的三个核心概念&#xff1a;线程安全性、线程同步和原子性。这些概念对于确保我们的程序在多线程环境中正确、高效地运行至关重要。 线程安全性 首先&#xff0c;什么是线程…

51单片机-串口通信(单片机和PC互发数据)

作者&#xff1a;Whappy 时间&#xff1a;2024.9.3 关于串口的疑问&#xff1f; 根据我的代码是不是初始化完成串口之后&#xff0c;只要我们使用串口发送数据就会触发中断&#xff1f; &#xff08;在文章下面&#xff09; ChatGPT said: ChatGPT 是的&#xff0c;根据…

[AWS云]EC2扩容磁盘之linux系统

背景&#xff1a; ec2的磁盘存储满了&#xff0c;需要扩容。 1.控制台修改存储大小&#xff1a; 2. 3.登录服务器&#xff0c;刷新磁盘&#xff1a; 云盘扩容 growpart /dev/vdb 1对ext4扩容命令resize2fs /dev/vdb1对xfs扩容命令xfs_growfs /dev/vdc1

传统CV算法——基于opencv的答题卡识别判卷系统

基于OpenCV的答题卡识别系统&#xff0c;其主要功能是自动读取并评分答题卡上的选择题答案。系统通过图像处理和计算机视觉技术&#xff0c;自动化地完成了从读取图像到输出成绩的整个流程。下面是该系统的主要步骤和实现细节的概述&#xff1a; 1. 导入必要的库 系统首先导入…

openlayers+vite+vue3实现规划某一特定行政区(二)

在前一期实现离线地图初始化的基础上&#xff0c;本文中主要阐述如何实现规划某一特定行政区&#xff0c;并展示其行政区的区县名称。 提示&#xff1a;因前文中阐述了如何实现离线地图的初始化&#xff0c;所以在此不再进行书写并详解初始化的过程和流程&#xff0c;如有不明…

MySQL简介和管理

目录 一、数据库基本概念 1.1、数据 1.2、表 1.3、数据库 1.4、数据库管理系统 1.5、数据库系统 二、数据库发展史 2.1、第一代数据库 2.2、第二代数据库 2.3、第三代数据库 三、数据库类型 3.1、关系型数据库 3.2、关系型数据库应用 3.3、非关系型数据库 3.4、…

【Python】数据分析分类图可视化

目录 条形图 箱形图 散点图 分簇散点图 小提琴 分簇小提琴 条形图 条形图是一种直观的图表形式&#xff0c;它通过不同长度的矩形条&#xff08;即“条形”&#xff09;来展示数值变量的中心趋势估计值&#xff0c;其中每个矩形的高度直接对应于该组数据的某个中心量度&…

若依微服务Admin控制台不显示ruoyi-file问题解决

本地启动完若依微服务,发现Admin控制台只显示了6个服务,其中ruoyi-file启动成功,但是没有在Admin控制台中显示处理,本章问题,给出这个问题的解决办法。 一、什么是服务监控 监视当前系统应用状态、内存、线程、堆栈、日志等等相关信息,主要目的在服务出现问题或者快要出…

JMeter 安装使用

JMeter 安装使用 a.安装 下载链接:Apache JMeter - Download Apache JMeter 环境变量 打开 cmd 输入 jmeter&#xff0c;即可启动 b.使用 http请求接口 300 个线程设置 1 s 的预热时间 右键 start

【STM32+HAL库】---- 基础定时器中断控制LED

硬件开发板&#xff1a;STM32G0B1RET6 软件平台&#xff1a;cubemaxkeilVScode1 新建cubemax工程 1.1 配置系统时钟RCC 1.2 配置LED LED由PA5引脚控制&#xff0c;选择PA5引脚&#xff0c;选择GPIO_Output模式 1.3 定时时间的计算 T ( 预分频系数 1 ) ( 重装载值 1 ) 时…

数仓基础(九):各大公司实时数仓实践

文章目录 各大公司实时数仓实践 一、网易实时数仓实践 二、汽车之家实时数仓实践 三、顺丰实时数仓实践 四、​​​​​​​腾讯实时数仓实践 五、​​​​​​​​​​​​​​滴滴实时数仓实践 ​​​​​​​​​​​​​​各大公司实时数仓实践 一、网易实时数仓实践…

Opencv实现提取卡号(数字识别)

直接开始 实行方法 解析命令行参数&#xff1a;使用argparse库来解析命令行输入&#xff0c;确保用户提供了输入图像和模板图像的路径。 读取模板图像&#xff1a;使用cv2.imread()函数读取模板图像的路径&#xff0c;并显示原始图像。 图像预处理&#xff1a; 将图像转换为…