阻塞队列(模拟实现)
概念
阻塞队列是带有阻塞功能的队列
特性
当队列满的时候,继续入队列,就会出现阻塞,阻塞到其他线程从队列中取走元素为止
当队列空的时候,继续出队列,也会发生阻塞,阻塞到其他线程往队列中添加元素为止
特点
阻塞队列有着解耦合和削峰填谷的主要特点
1.解耦合
两个服务器A,B,服务器A负责输送用户请求给服务器B,服务器B负责解决用户请求,但是两个服务器之间不是直接联系起来的,而是有一个阻塞队列在两个服务器之间,服务器A将请求输送给阻塞队列,服务器B从阻塞队列中获取请求,这样两个服务器之间就不是直接联系,耦合性就被降低。
耦合性降低可以避免出现一个服务器发生错误导致另一个服务器也发生错误的情况
2.削峰填谷
同样是两个服务器A,B,服务器A负责输送用户请求给服务器B,有一个阻塞队列在两个服务器之间,当出现莫种特殊情况,导致服务器A输送大量的数据到队列中,由于阻塞队列满了再添加数据就会发生阻塞等待,所以服务器B处理数据的节奏不会被影响,但要是没有阻塞队列,服务器A和服务器B是直接连接的话,很可能服务器A输送大量的请求给服务器B会导致服务器B崩溃
系统提供的阻塞队列的使用
BlockingQueue<Integer> queue=new ArrayBlockingQueue(); //底层是顺序表
BlockingQueue<Integer> queue=new LinkedBlockingQueue(); //底层是链表
BlockingQueue<Integer> queue=new PriorityBlockingQueue(); //底层是优先级队列(堆)
调用put方法是添加数据到队列中,调用take方法是弹出队列中的数据,由于BlockingQueue实现了Queue接口,所以它也有offer和poll等方法,但只有put和take方法是带阻塞的,所以推荐使用put和take方法
代码展示
class MyBlockingQueue{//用循环顺序表来作为阻塞队列的底层实现private String[]items=new String[1000];//数据存在的范围是[head,tail)//避免出现内存可见性和指令重排序的问题,要对变量加上volatile//指向头部的指针private volatile int head=0;//指向尾部的指针private volatile int tail=0;//记录阻塞队列中的数据个数private volatile int size=0;//put和take方法在多线程中涉及到多个线程改变同一个变量,所以要加上锁//向阻塞队列插入数据public void put(String elem) throws InterruptedException {synchronized(this){//判断队列是否满了while (size>=items.length){ //不一定阻塞等待是被notify正常唤醒的,也就不一定队列真的不满了,所以要用while循环多次判断//直到真的队列没满才进行接下来的操作(wait进行阻塞等待推荐和while一起使用,多次判断是否满足唤醒条件)this.wait(); //当队列满了就进入阻塞等待}items[tail]=elem;tail++;size++;if(tail>=items.length){tail=0;}this.notify(); //当向阻塞队列插入数据后,便可以唤醒弹出数据的阻塞状态}}//弹出阻塞队列中的数据public String take() throws InterruptedException {synchronized(this){//判断阻塞队列是否为空while (size==0){//不一定阻塞等待是被notify正常唤醒的,也就不一定队列真的不为空,所以要用while循环多次判断//直到真的队列不为空才进行接下来的操作(wait进行阻塞等待推荐和while一起使用,多次判断是否满足唤醒条件)this.wait();}String elem=items[head];head++;size--;if(head>=items.length){head=0;}this.notify(); //弹出一个数据后队列不满了就可以唤醒插入数据的阻塞状态return elem;}}}
代码分析
1.该代码中实现阻塞队列的底层结构是很简单的循环数组
2.由于要满足多线程编程,而put和take操作涉及到多个线程修改同一个变量的问题,所以需要用synchronized给put和take方法加锁,而为了防止出现内存可见性和指令重排序问题,对于在多线程中要进行读取修改的变量加上volatile关键字,防止编译器进行优化。
关于synchronized和内存可见性和指令重排序可以看线程安全问题,线程安全问题(内存可见性),线程安全问题(指令重排序)
3.如何实现阻塞呢?在put方法中,如果队列满了,那就要进入阻塞等待,就用synchronized加锁的对象调用wait方法进入阻塞等待,只有当take方法执行成功,才能调用notify唤醒put方法中阻塞等待的线程。
同样在take方法中,如果队列空了,那就要进入阻塞等待,就用synchronized加锁的对象调用wait方法进入阻塞等待,只有当put方法执行成功,才能调用notify唤醒take方法中阻塞等待的线程。关于wait于notify可以看通过wait和notify来协调线程执行顺序
4.put和take方法要对同一个对象进行加锁,因为put和take中要修改的变量有相同的,所以当多个线程调用put和take方法时存在线程安全问题,所以要对同一个对象进行加锁。
5.判断是否进入阻塞等待的条件是一个while循环(推荐wait()与while一起使用),因为不一定阻塞等待wait是被notify正常唤醒的,也就不一定是否真的满足队列不满或者不空的条件,所以要进行多次判断,要是队列依然还是满或空的话就要再次进入阻塞等待
相关文章:
阻塞队列(模拟实现)
概念 阻塞队列是带有阻塞功能的队列 特性 当队列满的时候,继续入队列,就会出现阻塞,阻塞到其他线程从队列中取走元素为止 当队列空的时候,继续出队列,也会发生阻塞,阻塞到其他线程往队列中添加元素为止 特…...

VScode中python的相对路径与绝对路径 FileNotFoundError: [Errno 2] No such file or directory
VScode中,python里的相对路径是相对于当前工作目录来定位的,而当前的工作目录在VScode中下方的终端窗口会有提示: 说明此时的工作目录并非当前python文件所在的目录,而是C:\Users\xxxxx(你的用户名)。因此,使用VScode…...
Unity XML2——C#读写XML
一、XML 文件的存放位置 (一)只读不写的 XML 放在 Resouces 或者 StreamingAssets 文件夹下,详见 Unity基础3——Resources资源动态加载_weixin_53163894的博客-CSDN博客。 (二)动态存储的 XML 放在 Applica…...

带wiringPi库的交叉编译 ---宿主机x86Ubuntu,目标机ARMv8 aarch64(香橙派)
带wiringPi库的交叉编译如何进行 先交叉编译wiringPi库,编译出的库适合香橙派,这时候交叉编译可执行程序的平台和链接库的格式也是正确的,然后通过-I和-L来指定链接的wiringPi库的头文件和库的位置,但是现在还没有学习过…...
数据仓库基础知识
什么是数据仓库? 数仓,DataWarehouse,是一个 面向主题的、集成的、稳定的、与时间相关的 数据集合。 而这个数据集合的建立,是为了支持管理者的决策过程。 也就是说,我们通过建设数仓,为业务中的流程改进、…...

M 芯片的 macos 系统安装虚拟机 centos7 网络配置
centos 安装之前把网络配置配好或者是把网线插好 第一步找到这个 第二步打开网络适配器 选择图中所指位置 设置好之后 开机启动 centos 第三步 开机以后 编写网卡文件保存 重启网卡就可以了,如果重启网卡不管用,则重启虚拟机即可 “ ifcfg-ens160 ” 这…...

AcWing 3708. 求矩阵的鞍点
输入样例: 3 4 1 2 3 4 1 2 3 4 1 2 3 4输出样例: 1 4 4 2 4 4 3 4 4 #include<bits/stdc.h> using namespace std; const int N1010; int n,m,a[N][N],x[N],y[N],flag1; int main(){scanf("%d%d",&n,&m);for(int i1;i<n;i…...

web前端开发工程师的具体职责范本(合集)
web前端开发工程师的具体职责范本1 职责: 1.负责web前端架构的搭建,核心业务功能开发和核心代码编写。 2.配合产品经理,实现产品UI和交互方面的需求,持续界面优化,提升用户体验。 3.参与相关业务需求变更评审。 4.…...

从源程序到可执行文件的四个过程
从源程序到可执行文件的四个过程 预处理编译汇编链接 程序要运行起来,必须要经过四个步骤:预处理、编译、汇编和链接,如下图所示: -E选项:提示编译器执行完预处理就停下来,后边的编译、汇编、链接就先不执…...

C++部署学习
gcc -E src/main.c -o src/main.i gcc -S src/main.c -o src/main.s gcc -C src/main.c -o src/main.o gcc src/main.c -o exec ./exec...
linux下lazarus开发ide里 BGRAControls控件库comboBox示例
下载开发工具 ftp://ftp.freepascal.org/pub/lazarus/releases/Lazarus%20Linux%20amd64%20DEB/Lazarus%202.2.6/https://sourceforge.net/projects/lazarus/files/Lazarus%20Linux%20amd64%20DEB/Lazarus%202.2.6/ sourceforge下载可能比较慢,选择 下载有问题&…...
Redis学习路线(9)—— Redis的场景使用
默认做好了其它的前提,只专注于Redis使用 一、短信登录 在没有Redis数据库时,我们会基于Session实现登录(利用令牌进行授权),是怎么实现的呢? (一)基于Session的短信登录功能 1、…...

糟了,数据库主从延迟了!
前言 在实际的生产环境中,由单台MySQL作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面 因此,一般来说都是通过集群主从复制(Master-Slave)的方式来同步数据&…...
VUE,子组件给父组件传递参数,props 自定义属性,ref
<template><div><!-- 子传父 --><!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 --><AA :getAAname"getAAname"/><h1>AA:{{aaname}}</h1><!-- 通过父组件给子组件绑定一个自定…...
【Oracle系列】- Oracle数据迁移
【Oracle系列】- Oracle数据迁移 文章目录 【Oracle系列】- Oracle数据迁移一、概述二、数据迁移方案三、模拟迁移方案四、迁移步骤五、迁移方案及其实施细则5.1 exp/imp逻辑备份与恢复5.2 Storage存储迁移5.3 利用data guard迁移 一、概述 最近在做公司软件系统盘点时&#x…...

Linux环境安装MySQL(详细教程)
1、下载MySQL MySQL官网:MySQLhttps://www.mysql.com/ 下载社区版(免费,但不提供技术支持) 简单说明一下rpm和tar包的区别: tar 只是一种压缩文件格式,所以,它只是把文件压缩打包 rpm…...
23. Mysql中的排序规则
文章目录 Mysql中的排序规则1. 数据库默认的排序规则2. 查看表的排序规则2.1 查看表排序规则2.2 查看字段排序规则 3.修改排序规则3.1 修改库3.2 修改表3.3 修改字段 Mysql中的排序规则 1. 数据库默认的排序规则 mysql8的默认排序方式是 utf8mb4_0900_ai_ci mysql5的默认排序…...
MongoDB 基础学习记录
MongoDB 基础 mongoDB 是由 C语言编写,基于分布式文件存储的开源数据库系统,是一个 nosql 数据库. 在高负载的情况下,添加更多的节点,保证服务器性能,MongoDB 旨在为 web 引用提供可扩展的高性能存储解决方案,将数据存储为给文档, 数据结构由键值(key,value)对组成,MongoDB 文…...

Visual Studio2022报错 无法打开 源 文件 “openssl/conf.h“解决方式
目录 问题起因问题解决临时解决方案 问题起因 近一段时间有了解到Boost 1.82.0新添加了MySQL库,最近一直蠢蠢欲动想要试一下这个库 所以就下载了源码并进行了编译(过程比较简单,有文档的) 然后在VS2022中引入了Boost环境…...

【更新公告】Airtest更新至1.3.0.1版本
1. 前言 本次更新为Airtest库更新,版本提升至1.3.0.1版本,主要新增了一些iOS设备相关的装包等接口,以及封装了一些tidevice常用接口。更多更新详情,详见我们下文的描述。 2. 新增iOS设备接口 1)iOS安装接口…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...

spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...