阻塞队列的理解-创新互联

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

创新互联公司专注于台江网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供台江营销型网站建设,台江网站制作、台江网页设计、台江网站官网定制、微信小程序服务,打造台江网络公司原创品牌,更为您提供台江网站排名全网营销落地服务。

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

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

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

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

2.1消息队列的作用:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

四.手动实现阻塞队列

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;
        }

    }
}

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

1.

2.

3.

4.

5.

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


分享文章:阻塞队列的理解-创新互联
分享地址:http://hbruida.cn/article/dchjgd.html