阻塞队列的理解

简介: 阻塞队列的理解

一.阻塞队列如普通队列一般,从队尾插入,队首取出,与一般队列不同的是,在插入元素时,我们需要判断一下,如果队列已满,我们需要进行等待,及进入阻塞状态

取出元素同理,我们在取出元素前需要进行判断,如果队列内元素为空,我们则需要等待,进入阻塞状态

举一个实际生活中的应用案例进行讲解:

486468e0da702885135e5169dd8a97a8.png

二.消息队列:消息队列是对阻塞队列的一种典型应用,是基于生产者和消费者模型来实现的,与阻塞队列不同的是,消息队列是在阻塞队列的基础上,为其中元素加入了‘标签’(topic),便于根据不同的业务场景调用不同的元素,换句话说,消息队列对储存在其中的元素进行了分类(基于真实的业务场景要求)。

消息队列是在真实的业务场景的要求驱使下,对队列这一数据结构进行了自定义的功能开发,满足真实业务场景的需求,我们称类似消息队列的框架或是软件为‘中间件’。

2.1消息队列的作用:

①实现了解耦操作:我们一般对程序的要求是高内聚和低耦合,那么何为高内聚和低耦合呢?

高内聚:我们要求业务强相关的功能或者代码组织在一起,而不是分散在不同的类中,这样有利于后续对代码的维护,我们称这种代码的组织方式为高内聚

低耦合:对于业务场景不强相关的或者是重复的代码,我们尽量将其抽象为不同的接口,其他方法想要使用代码直接调用接口即可,而不是将很多相同的代码写在不同的方法中,这样有利于我们后续对代码的维护(如果代码逻辑发生改变,我们只需要修改该接口即可,而不必修改全部的代码,大大提示了修改的效率)。

我们通过画图对阻塞队列的解耦功能进行讲解:

991024c74951855d7cff90be2a1b71d3.png

这是在没有添加阻塞队列时功能的改变伴随的修改很多,这种耦合性相对较高,我们通过加入阻塞队列降低耦合性:

fd81d356adda455bdc378e9e6c1092ce.png

②实现了数据的‘削峰填谷’:我们假设一种业务场景,如果在一时间用户对前端服务器的访问量猛然增加很多,随着前端服务器访问量增加,则发送给后端服务器的需求也猛然增加,即使可能前后端服务器的某一个服务器能够承受的流量高于另一个,一旦其中一个瘫痪,另一个也会因为接收不到数据或者无法获取恢复也无法实现功能的实现,类似下图:

0ea642c1d5cb1a41baa6fb46c71cc6f5.png

但是如果加入了阻塞队列作为数据传输的中间组件,情况则会大有不同:


如果A服务器的流量猛增,其可以将访问请求迅速传输给消息队列,因为消息队列的容量很大,能够很大程度上环节服务器A的压力,避免其瘫痪,提高了服务器的安全性,另一方面,即使A因为流量过大瘫痪,由于A和B并不直接交互,消息队列仍然可以将请求传输给B,B仍能对请求作出响应,也就是说服务器A的瘫痪并不影响服务器B功能的实现。

8b876bdce631747743385581134a6b05.png

f8133f76451d67b76d925eb5370ab8f5.png

4de47bc6405d3bdb22c5293ccb01b9ac.png


14842ff6c761c4087905352f0663f62d.png

③:能够实现异步操作:何为异步操作?就是如果服务器A发送请求,其不必等待服务器B对其回应后再去执行其他任务,而是先返回给用户提示,然后去执行其他任务,等待B回复后再将回复传达给用户即可,但是如果A和B如果直接交互,则很难实现异步操作。而一旦加入阻塞队列,A将请求发送给阻塞队列,阻塞队列将请求传输给B并等待B的返回即可,在此期间A可移执行其他任务,这便实现了异步操作。

f5d28f76f1f380731ce213ca2f60b02d.png

三.系统提供的阻塞队列:

3cd00ebf892ccf1b47094f91f3e631af.png

它有三个实现类:我们应该根据不同的业务场景选择不同的实现类

324ad6123fb4a8be781ccc64630fe4db.png

其中每个实现类中都包含不同的加入元素和取出元素的实现方法:

6c371bc2ccf807dcf0973031ed862873.png

6c371bc2ccf807dcf0973031ed862873.png

82ca54abe77be670d40b1b84b6822822.png

而像put()和take()这种会抛出interruptedException异常的则是支持多线程情况下应用的

我们创建容量为3的队列并演示其应用

18b78f9fa2def1c8bd1e7e9b6b5fde84.png

443c6247d7d525da40644e8aca5de663.png

同理,将其注释则可恢复正常:

ee272299e89e23211f5355c1b166b572.png

四.手动实现阻塞队列

public class MyBlockingQueue {

   //为了避免多线程情况下的读写不一致情况,给变量加volatile

   private volatile int front;

   private volatile int tail;

   private volatile int size;

   private int[]element=new int[1000];

   //加入方法

   public void put(Integer value) throws InterruptedException {

       synchronized (this){

 

           //判断是否已满

           while(size==element.length){

               System.out.println("当前队列已满");

               this.wait();

           }

           //加入操作

           element[tail]=value;

           tail=(tail+1)% element.length;

           size++;

           this.notifyAll();

       }

   }

   //去除元素操作

   public int remove () throws InterruptedException {

       synchronized(this){

 

           //判断是否为空

           while(size==0){

               System.out.println("当前队列为空");

               this.wait();

           }

           int value=element[front];

           //删除操作

           front=(front+1)%element.length;

           size--;

           this.notifyAll();

           return value;

       }

 

   }

}

我们对该手动实现的阻塞队列进行一步一步的讲解:

3f894638a896a687c4097f92715d0a9a.png

1fa0736a06078218f15b242b2716d7eb.png08f31bd864bbc4e9bcfd14c40c797187.png


1fa0736a06078218f15b242b2716d7eb.png

cd6d904bf653f19bfc3016d407f992c1.png

55eea30b6986bdd14524c9b4fbd4fd65.png

3ebccf43b12f2b47aad833d291bf500a.png

d20e3873f419b0edd98b7440582aac1d.png


相关文章
|
1月前
|
运维 安全 Linux
Xshell 8密钥登录Linux教程(Xshell 8如何配置SSH公钥私钥安全登录)
本教程参考:http://www.dnuhf.cn详解Xshell 8配置SSH密钥登录Linux服务器的完整流程:从生成RSA/ED25519密钥对、导出公钥,到服务器端部署authorized_keys及Xshell会话设置。操作清晰,小白友好,显著提升安全性,防范暴力破解。(239字)
|
消息中间件 XML 网络协议
『NLog』.Net使用NLog使用方式及详细配置(输出至文件/RabbitMQ/远程网络Tcp)
📣读完这篇文章里你能收获到 - Nlog输出至文件/RabbitMQ/远程网络Tcp配置文档 - Nlog配置参数详解 - .NET CORE项目接入
6729 0
『NLog』.Net使用NLog使用方式及详细配置(输出至文件/RabbitMQ/远程网络Tcp)
|
Linux Docker 容器
docker 国内镜像源
【8月更文挑战第26天】
6644 1
|
XML JSON Ubuntu
Python实用记录(十五):PyQt/PySide6打包成exe,精简版(nuitka/pyinstaller/auto-py-to-exe)
本文介绍了使用Nuitka、PyInstaller和auto-py-to-exe三种工具将Python的PyQt/PySide6应用打包成exe文件的方法。提供了详细的安装步骤、打包命令和参数说明,适合新手学习和实践。
7438 0
|
JSON 前端开发 JavaScript
搭建Vue3组件库:第十六章 品质保证:发布覆盖率测试报告
本章介绍如何发布你的组件代码覆盖率已经获取对应徽章。
1170 0
搭建Vue3组件库:第十六章 品质保证:发布覆盖率测试报告
|
XML 开发框架 编译器
基于Qt编写超精美自定义控件
一、前言 无论是哪一门开发框架,如果涉及到UI这块,肯定需要用到自定义控件,越复杂功能越多的项目,自定义控件的数量就越多,最开始的时候可能每个自定义控件都针对特定的应用场景,甚至里面带了特定的场景的一些设置和处理,随着项目数量的增多,有些控件又专门提取出来共性,做成了通用的自定义控件,意味着控件主要做外观处理,用户根据不同的场景需要,设置不同的外观和规则,就这样搞来搞去搞到现在,已经超过了202个控件,慢慢的积累迭代和更新,历经超过9年的时间不断的完善,尤其是对不同Qt版本、不同编译器、不同操作系统的支持,其中Qt6改动比较大,很多方法或者类改名或者废弃了,需要用类似的方法处理。
372 0
|
存储 XML 缓存
详解Hadoop3.x新特性功能-HDFS纠删码
详解Hadoop3.x新特性功能-HDFS纠删码
1084 0
详解Hadoop3.x新特性功能-HDFS纠删码
|
JSON Prometheus Kubernetes
Promtail Pipeline 日志处理配置
Promtail Pipeline 日志处理配置
|
移动开发 图形学 UED
市场上已知的AVG编辑器调查分析
市场上已知的AVG编辑器调查分析
1074 0