Javaee:阻塞队列和生产者消费者模型

文章目录

什么是阻塞队列

阻塞队列是一种支持阻塞操作的队列,在多线程中实现通线程之间的通信协调的特殊队列

java中的主要阻塞队列

java中的阻塞队列是一个接口BlockingQueue<>

带有实例化类有:

ArrayBlockingQueue(有界队列)
LinkedBlockingQueue(无界队列)
ProrityBlockingQueue(FIFO队列)

阻塞队列不仅继承了队列的所有方法,还提供了带有阻塞效果的put方法和take方法

put(E e):将元素插入队列,如果队列满,则等待直到队列有空间。
take():从队列中取出并移除元素,如果队列为空,则等待直到队列有元素。

特点

线程安全

阻塞特性

队列为空,尝试出队列,出队列操作就会阻塞,阻塞到其他线程添加元素为止

队列为满,尝试进队列,进队列操作也会阻塞,阻塞到其他线程取走元素为止

以上是线程一往阻塞队列添加元素,线程二从阻塞队列中移除元素

理解有界和无界

有界:在实例化对象的时候,可以在构造方法传参,表示阻塞队列能容纳的最大元素个数

无界:没有设置固定大小的队列,表示可以存储的元素个数范围很大

生产者消费者模型


阻塞队列是生产者消费者模型的交易场所

举个生活中的例子

包饺子

奶奶负责擀饺子皮,奶奶把饺子皮放到一个容器里,我和妈妈把饺子皮从容器中拿出来包饺子。

饺子皮------>资源

奶奶------>生产者

我和妈妈------>消费者

容器------>交易场所(阻塞队列)

阻塞队列发挥的作用

解耦合

举例

服务器A直接与服务器B进行交互,一旦服务器A中的代码发生改变,服务器B越需要做出相应的改变,也就是他们之间的关联度高,耦合度高

解耦合------通过阻塞队列

服务器A不直接与服务器B进行交互,而是通过阻塞队列这个交易场所进行交互,降低了服务器之间的关联度

在生产者消费者模型中的应用

阻塞队列通过充当中间缓存,允许生产者先把数据放入队列,消费者在有空闲时再取出处理,这样就不会因为速度不一致而导致数据丢失或重复处理

削峰填谷

如果服务器A传给B的数据量激增,服务器B没有那么大的接收量,就会瞬间过载

削峰填谷------阻塞队列

在请求量突然增加的情况下,阻塞队列可以缓冲住大量的生产者请求,避免消费者瞬时过载。

当生产量较小时,消费者可以逐步消费队列中积累的数据,从而实现负载平衡和资源优化。

模拟实现阻塞队列

put方法

java 复制代码
public void put(String elem) throws InterruptedException {
        synchronized(locker) {//保证原子性
            // 使用while循环来检查队列是否已满,以处理虚假唤醒和条件变化的情况
            while (size >= data.length) {//if的话会出问题,使用wait需要搭配while进行二次判断,如果唤醒wait之后,size还是为0,那么执行下面的操作就会出问题
               //如果队列已满,则当前线程等待,直到被其他线程唤醒
                locker.wait();//抛一下异常
            }
            data[tail] = elem;
            tail++;
            if (tail >= data.length) {
                tail = 0;//便于理解
                //tail=(tail+1)%data.length;

            }
            size++;
            locker.notify();//说明不为空就去唤醒take的wait
        }
    }

take方法

java 复制代码
public String take() throws InterruptedException {
        synchronized (locker) {//保证原子性
            // 使用while循环来检查队列是否为空,以处理虚假唤醒和条件变化的情况
            if (size == 0) {
                locker.wait();// 如果队列为空,则当前线程等待,直到被其他线程唤醒
            }

            String ret = data[head];
            head++;
            if (head >= data.length) {
                head = 0;
            }
            size--;
            // 在取出元素并更新队列状态后,通知其他等待的线程
            locker.notify();//相互唤醒,说明没满,就去唤醒put的wait
            return ret;
        }
    }

生产者消费者模型

java 复制代码
Thread producer=new Thread(()->{
            int n=0;
            try {
                while(true){
                    queue.put(n+" ");
                    System.out.println("生产元素"+n);
                    n++;
                }
            } catch (InterruptedException e) {
               throw new RuntimeException(e);
            }
        },"生产者");
        Thread consumer=new Thread(()->{
            while(true){
                String n=null;
                try {
                        n=queue.take();
                        System.out.println("消费元素"+n);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        Thread consumer2=new Thread(()->{
            while(true){
                String n=null;
                try {
                    n=queue.take();
                    System.out.println("消费元素"+n);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
相关推荐
F-2H1 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
苹果酱05671 小时前
「Mysql优化大师一」mysql服务性能剖析工具
java·vue.js·spring boot·mysql·课程设计
_oP_i2 小时前
Pinpoint 是一个开源的分布式追踪系统
java·分布式·开源
mmsx2 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
武子康2 小时前
大数据-258 离线数仓 - Griffin架构 配置安装 Livy 架构设计 解压配置 Hadoop Hive
java·大数据·数据仓库·hive·hadoop·架构
豪宇刘3 小时前
MyBatis的面试题以及详细解答二
java·servlet·tomcat
秋恬意3 小时前
Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
java·数据库·mybatis
FF在路上4 小时前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
真的很上进4 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
众拾达人5 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言