阻塞队列(java)

一.定义

多线程 代码常用的一种数据结构

是一种特殊的队列

二.特性

1,其线程安全

2,带有阻塞特性

a)如果队列为空,执行出对列操作,发生阻塞,直到其他线程往队列中添加元素

b)如果队列为满,执行入队列操作,发生阻塞,,直到其他线程从队列中取走元素

三.存在意义

阻塞队列,最大的意义就是来实现"生产者消费者模型"-----一种多线程编写方式.

四.生产者消费者模型

(一)意义

1.解耦合

比如在一个简单的分布式系统

此时当服务器A和服务器B直接进行信息交互,耦合性较高

1)如果服务器B出现问题,服务器A也会被影响到

2)如果在添加一个C服务器与服务器A交互,服务器A必定要做出代码修改

如果我们使用粗阻塞队列帮我们完成生产者消费者模型,就会变成下面这种情况:

把阻塞队列封装成单独的服务器程序,部署到特定的机器上,这时候把队列称为消息队列
此时,耦合性就会降低

1)如果B出现问题,不会对A产生直接影响,只是没办法处理队列信息,发生阻塞

2)如果后序增加一一个C服务器那么可以直接从队列获取元素,A服务器可以不进行修改

2.削峰填谷

在第一种结构下,一旦客户端发起请求过多,每次A都会把消息立即发给B,如B不如A的硬件设施好,也可能B要操作数据库,承担不了这个信息量,就会挂掉.

但是在引入生产者消费者模型后,就会得到改善

比如:A每分钟处理1000次请求,B也处理1000次请求

削峰:

但是当A这面处理3000次请求时,如果让B也处理3000次请求,那B就会挂掉,但是这是由于存在阻塞对列,B依然可以会处理1000次请求来执行,只不过客户端和服务器A需要等待响应,但好过系统挂掉.

填谷:

当上述情况过去了,A接收到的请求恢复正常,B会逐渐处理队列中的请求

(二)代码使用(BlockingQueue)

标准库中,为阻塞队列提供了基于链表和数组的实现的方式,代码如下:

    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> queue = new LinkedBlockingQueue<>();
        queue.put("123");
        queue.put("234");
        queue.put("345");
        System.out.println(queue.take());
        System.out.println(queue.take());
        System.out.println(queue.take());
        System.out.println(queue.take());
        System.out.println("运行结束");
    }

运行结果:  队列为空时,发生阻塞,并未执行后序代码

(三)自己实现阻塞队列

1)代码实现

class MyblockingQueue{
    private String[] data = new String[10];//阻塞队列大小10
    //对列起始位置
    private volatile int head = 0;
    //队列末尾元素位置 的下一个位置
    private volatile int tail = 0;
    //队列中有效个数
    private volatile int size = 0;
    private Object object = new Object();
    //入队方法
    public void put(String elem) throws InterruptedException {
        synchronized (object){
            //当队列元素满了
            while (size==data.length){
                System.out.println("等待--->为满");
                object.wait();
            }
            data[tail] = elem;
            tail++;
            //如果到了数组末尾需要重新置0
            if(tail==data.length){
                tail = 0;
            }
            size++;
            //解除队列为空的等待
            if(size==1){
                //System.out.println("解除队列为空的等待");
                object.notify();
            }
        }

    }
    //出队列
    public String take() throws InterruptedException {
        synchronized (object){
            //如果队列为空
            while (size==0){
                System.out.println("等待--->为空");
                object.wait();
            }
            String ret = data[head];
            head++;
            if(head==data.length){
                head = 0;
            }
            size--;
            //解除队列为满的等待
            if(size<data.length){
                //System.out.println("解除队列为满的等待");
                object.notify();
            }
            return ret;
        }
    }

}
public class Demo2 {
    public static void main(String[] args) {
        //生产者 消费者,分别用一个线程表示
        MyblockingQueue queue = new MyblockingQueue();

        //消费者
        Thread t1 = new Thread(()->{
            while (true){
                try {
                    String result = queue.take();
                    System.out.println("消费者消费元素:" + result);
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        Thread t2 = new Thread(()->{
            int num = 0;
            while (true){
                try {
                    System.out.println("生产者生产元素:" + num);
                    queue.put(num+"");
                    Thread.sleep(10);

                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                num++;
            }
        });
        t2.start();
        t1.start();
    }
}

2)执行结果:

3)细节处理

(1)while()interrupt可能会中断wait状态

(2)volatile避免内存可见性(判定,查看)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值