6.阻塞队列-bite

阻塞队列优点1:让多个服务器之间充分的解耦合

阻塞队列同样也是一个符合先进先出规则的队列

生产者消费者模型,是实际开发中非常有用的一种多线程开发手段!!!尤其是在服务器开发的场景中

假设,有两个服务器, AB,A作为入口服务器直接接收用户的网络请求,B作为应用服务器,来给A提供一些数据

在这里插入图片描述

如果不使用生产者消费者模型此时A和B的耦合性是比较强的!!在开发A代码的时候就得充分了解到B提供的一些接口.开发B代码的时候也得充分了解到A是怎么调用的—旦想把B换成C,A的代码就需要较大的改动,而且如果B挂了,也可能直接导致A也顺带挂了.

使用生产者消费者模型,就可以降低这里的耦合

在这里插入图片描述

对于请求:A是生产者,B是消费者.对于响应:A是消费者,B是生产者.阻塞队列都是作为交易场所

A只需要关注如何和队列交互,不需要认识BB也只需要关注如何和队列交互,也不需要认识A队列是不变~~
如果B挂了,对于A没啥影响~~如果把B换成C,A也完全感知不到…

阻塞队列优点2:可以对请求进行削峰填谷

在这里插入图片描述

A暴涨=>B暴涨
A作为入口服务器,计算量很轻,请求暴涨,问题不大.
B作为应用服务器,计算量可能很大,需要的系统资源也更多.如果请求更多了,需要的资源进—步增加,如果主机的硬件不够,可能程序就挂了

如果使用阻塞队列:
在这里插入图片描述

"削峰”这种峰值很多时候不是持续的,就一阵,过去了就又恢复了
"填谷”B仍然是按照原有的频率来处理之前积压的数据

A请求暴涨=>阻塞队列的请求暴涨,由于阻塞队列没啥计算量,就只是单纯的存个数据,就能抗住更大的压力.
B这边仍然按照原来的速度来消费数据,不会因为A的暴涨而引起暴涨.B就被保护的很好,就不会因为这种请求的波动而引起崩溃.

手动实现一个阻塞队列

java标椎库中提供的的阻塞队列
在这里插入图片描述

队列可以基于数组实现, 也可以基于链表实现.
此处基于数组实现阻塞队列更简单,就直接写数组版本

class MyBlockingQueue {
    // 保存数据的本体
    private int[] data = new int[1000];
    // 有效元素个数
    private int size = 0;
    // 队首下标
    private int head = 0;
    // 队尾下标
    private int tail = 0;

    // 专门的锁对象
    private Object locker = new Object();

    // 入队列
    public void put(int value) throws InterruptedException {
        synchronized (locker) {
            if (size == data.length) {
                // 队列满了. 暂时先直接返回.
                // return;
                locker.wait();
            }
            // 把新的元素放到 tail 位置上.
            data[tail] = value;
            tail++;
            // 处理 tail 到达数组末尾的情况
            if (tail >= data.length) {
                tail = 0;
            }
            // tail = tail % data.length;
            size++;  // 千万别忘了. 插入完成之后要修改元素个数
            // 如果入队列成功, 则队列非空, 于是就唤醒 take 中的阻塞等待.
            locker.notify();
        }
    }

    // 出队列
    public Integer take() throws InterruptedException {
        synchronized (locker) {
            if (size == 0) {
                // 如果队列为空, 就返回一个非法值.
                // return null;
                locker.wait();
            }
            // 取出 head 位置的元素
            int ret = data[head];
            head++;
            if (head >= data.length) {
                head = 0;
            }
            size--;
            // take 成功之后, 就唤醒 put 中的等待.
            locker.notify();
            return ret;
        }
    }
}

public class Demo22 {
    private static MyBlockingQueue queue = new MyBlockingQueue();

    public static void main(String[] args) {
        // 实现一个简单的生产者消费者模型
        Thread producer = new Thread(() -> {
            int num = 0;
            while (true) {
                try {
                    System.out.println("生产了: " + num);
                    queue.put(num);
                    num++;
                    // 当生产者生产的慢一些的时候, 消费者就得跟着生产者的步伐走.
                    // Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        producer.start();

        Thread customer = new Thread(() -> {
            while (true) {
                try {
                    int num = queue.take();
                    System.out.println("消费了: " + num);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        customer.start();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值