阻塞队列的理解

简介: 阻塞队列的理解

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

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

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

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


相关文章
|
12月前
|
存储 安全 Java
阻塞队列《——》特殊的队列(先进先出)
阻塞队列《——》特殊的队列(先进先出)
40 0
|
12月前
|
算法 安全 Java
【阻塞队列BlockingQueue&非阻塞队列ConcurrentLinkedQueue&同步队列SyncQueue】
【阻塞队列BlockingQueue&非阻塞队列ConcurrentLinkedQueue&同步队列SyncQueue】
|
5月前
|
存储 安全 Java
实现一个阻塞队列
实现一个阻塞队列
39 0
|
5月前
|
存储 消息中间件 安全
关于阻塞队列
关于阻塞队列
49 0
阻塞队列BlockingQueue
阻塞队列BlockingQueue
48 0
阻塞队列BlockingQueue
|
存储 缓存 安全
BlockingQueue阻塞队列原理以及实现
BlockingQueue阻塞队列原理以及实现
113 0
|
存储 缓存 安全
JUC之阻塞队列解读(BlockingQueue)
JUC之阻塞队列解读(BlockingQueue)
|
安全
基于链表的有界阻塞队列 —— LinkedBlockingQueue
上一节看了基于数据的有界阻塞队列 ArrayBlockingQueue 的源码,通过阅读源码了解到在 ArrayBlockingQueue 中入队列和出队列操作都是用了 ReentrantLock 来保证线程安全。下面咱们看另一种有界阻塞队列:LinkedBlockingQueue。
173 0
|
安全
基于数组的有界阻塞队列 —— ArrayBlockingQueue
在阅读完和 AQS 相关的锁以及同步辅助器之后,来一起阅读 JUC 下的和队列相关的源码。先从第一个开始:ArrayBlockingQueue。
113 0
|
消息中间件 存储 Java
阻塞队列 BlockingQueue
学数据结构时学过队列,特点是FIFO,先进先出。那么什么阻塞队列呢?一起来看看。
阻塞队列 BlockingQueue