阻塞队列实现

发布时间:2023年12月24日

? 作者:小胡_不糊涂
🌱 作者主页:小胡_不糊涂的个人主页
📀 收录专栏:JavaEE
💖 持续更文,关注博主少走弯路,谢谢大家支持 💖

1. 什么是阻塞队列

阻塞队列是?种特殊的队列,遵守 “先进先出” 的原则。

阻塞队列能是?种线程安全的数据结构,并且具有以下特性:

  • 当队列满的时候,继续?队列就会阻塞,直到有其他线程从队列中取?元素。
  • 当队列空的时候,继续出队列也会阻塞,直到有其他线程往队列中插?元素。

阻塞队列的?个典型应?场景就是 “?产者消费者模型”。这是?种?常典型的开发模型。

生产者消费模型:
?产者消费者模式就是通过?个容器来解决?产者和消费者的强耦合问题。
?产者和消费者彼此之间不直接通讯,?通过阻塞队列来进?通讯,所以?产者?产完数据之后不?等待消费者处理,直接扔给阻塞队列,消费者不找?产者要数据,?是直接从阻塞队列?取

  1. 阻塞队列就相当于?个缓冲区,平衡了?产者和消费者的处理能力
  2. 阻塞队列也能使?产者和消费者之间解耦

2. 标准库中的阻塞队列

在 Java 标准库中内置了阻塞队列。如果我们需要在?些程序中使?阻塞队列,直接使?标准库中的即可。
在这里插入图片描述

  • BlockingQueue 是?个接?,真正实现的类是 LinkedBlockingQueue
  • put ?法?于阻塞式的?队列,take ?于阻塞式的出队列
  • BlockingQueue 也有 offer, poll, peek 等?法,但是这些?法不带有阻塞特性

示例:

public static void main(String[] args) throws InterruptedException {
    BlockingQueue<String> queue=new ArrayBlockingQueue<>(100);
    queue.put("aaa");//入队列--有阻塞功能的
    String elem=queue.take();//出队
    System.out.println(elem);//aaa
}

3. 模拟实现

方法

  1. 先实现普通队列–使用数组实现循环队列,保证实现出入队列的操作
  2. 加上线程安全–synchronized
  3. 加上阻塞队列
//模拟实现
class MyBlockingQueue{
    private String[] elems=null;//数组实现队列
    private int head=0;//队首
    private int tail=0;//队尾
    private int size=0;//元素个数

    private  Object loker=new Object();//锁对象

    public MyBlockingQueue(int capacity){
        elems=new String[capacity];
    }

    //入队列
    public void put(String elem) throws InterruptedException {
        //有读写操作的
        synchronized (loker) {
            //队列满了,进入阻塞
            while(size >= elem.length()) {
                loker.wait();
            }

            elems[tail] = elem;//新元素放入tail位置上
            tail++;
            //tail=tail%elems.length;
            if (tail >= elems.length) {
                tail = 0;//循环对列
            }
            size++;

            //当队列为空,只要有元素入队列就唤醒下面的wait
            loker.notify();
        }
    }

    //出队列
    public String take() throws InterruptedException {
        String tmp =null;
        synchronized (loker) {
            //队列为空
            while(size == 0) {
                loker.wait();
            }
            tmp = elems[head];
            head++;
            if (head >= elems.length) {
                head = 0;
            }
            size--;
            //当队列满了,只要有元素出队列就唤醒前面的入队列
            loker.notify();
        }
            return tmp;
    }
}
文章来源:https://blog.csdn.net/iLoyo_/article/details/135172200
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。