阻塞队列《——》特殊的队列(先进先出)

news2025/1/23 10:34:47

所谓的阻塞队列:就是带有阻塞特性的《——》线程安全的

  1. 如果队列为空,尝试出队列,就会阻塞等待,等到队列不为空为止
  2. 如果队列为满,尝试入队列,也会阻塞等待,等到队列不为满为止

这个东西非常有用,尤其是写多线程代码的时候,多个线程之间进行数据交互,可以使用阻塞队列来简化代码编写!

Java标准库提供了阻塞队列的使用:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

//阻塞队列
public class Main3 {
    public static void main(String[] args) throws InterruptedException{
        // BlockingDeque<>是一个接口,不能直接new,因此,可以new一个 BlockingDeque<>的实现类LinkedBlockingDeque<>()
        BlockingDeque<String> queue=new LinkedBlockingDeque<>();//基于链表实现
        //ArrayBlockingQueue<>()基于数组实现
        //put入队列
        queue.push("hello1");
        queue.push("hello2");
        //take出队列
        String result=null;
        result= queue.take();//取出队首元素
        System.out.println(result);
        
        result=queue.take();
        System.out.println(result);

        result=queue.take();
        System.out.println(result);
    }
}

上述代码的运行结果为:

上述代码,入队列两次,当第三次出队列的时候,会进行阻塞!!想要解除阻塞,就需要有另一个线程往阻塞队列中放入元素!!

编写一个“生产者消费者模型”,多线程使用阻塞队列

案列:包饺子~

生产者消费者模型:初心是啥??能解决啥问题??

能解决的问题有很多,最主要的是俩方面:

1.可以让上下游模块之间进行更好的“解耦合

耦合:两个模块之间的关联关系是强还是弱(关联越强,耦合越高)

写代码的要追求低耦合,避免代码牵一发动全身

内聚:

低内聚,相关联的东西没有放到一起,随便乱放的,

           相关联的代码没有放到一起,东一块西一块,

高内聚:相关联的代码,分门别类的规制起来

如:两个服务器A与服务器B之间,有没有阻塞队列的情况:

2.削峰填谷

A收到的请求数量是和用户行为相关的

用户行为是随机的情况,有些情况下会出现“峰值”,暴涨一波!如果A和B是直接调用的关系,A收到峰值,B也同样收到峰值!假设A平时收到的请求是1秒1W个,突然间A收到了1秒5W个请求,则B也会1秒出现5W个请求,此时如果B设计的时候,没有考虑峰值,可能会直接挂了~~

如果有了阻塞队列这种情况:此时A收到的请求多了,队列里的元素也就多了,此时A仍然可以按照之前的速率来取元素,则队列帮B承担了压力!

比如:三峡大坝的闸门《——》削峰填谷

接下来就编写一个“生产者消费者模型”多线程使用阻塞队列的情况!

阻塞队列的简单用法:

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

public class Main4 {
    public static void main(String[] args) {
        //阻塞队列
        BlockingDeque<Integer> blockingDeque=new LinkedBlockingDeque<>();
        //用法比较简单,重点在于如何实现一个阻塞队列

        //消费者
        Thread t1=new Thread(()->{
            while (true){
                try {
                    //从队列中取元素
                    int value = blockingDeque.take();
                    System.out.println("消费元素:"+ value);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();

        //生产者
        Thread t2=new Thread(()->{
            int value=0;
            while (true){
                try {
                    System.out.println("生产元素:"+value);
                    blockingDeque.put(value);
                    value++;
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //上述代码,让生产者每隔1s生产一个元素
        //让消费者直接消费,不受限制
        t2.start();
    }
}

上述代码的运行结果为:

重点:如何模拟写一个阻塞队列

泛型??普通程序猿很少在工作中会用到

一般实现库的程序员会涉及泛型

因此再后续面试的时候,尽量不要写泛型!!(重要)

能不用泛型就不用泛型~

不用泛型,直接用朴素的代码,假定有存储的元素为int,基于数组来实现队列

class MyBlockingQueue{
    private int[] items=new int[1000];//数组
    //约定[head,tail)队列的有效元素
    volatile private int head=0;//指向队首元素下标
    volatile private int tail=0;//指向队尾元素下标
    volatile private int size=0;//获取队列中的元素个数

    //入队列
    synchronized public void put(int elem) throws InterruptedException{
        if (size==items.length){
            //如果队列满了,插入失败
            //return;
            this.wait();
            //如果队列满了,就进行阻塞
            //出队列的notify()唤醒
        }
        //把新元素放到tail所在的位置上
        items[tail]=elem;
        tail++;

        //万一tail达到末尾,要让tail从头再来
        if (tail==items.length){
            tail=0;
        }
        //一样的写法,用:tail%items.length不高效
        //tail=tail%items.length;不推荐

        size++;
        this.notify();
    }

    //出队列
    synchronized public Integer take()throws InterruptedException{
        while (size==0){
            //return null;
            this.wait();
            //队列为空,阻塞等待
            //入队列的notify唤醒
        }
        int value=items[head];
        head++;//队首元素下标往后走
        if (head==items.length){
            head=0;
        }
        size--;
        this.notify();
        return value;
    }
}
public class Main5 {
    public static void main(String[] args) {
        MyBlockingQueue queue=new MyBlockingQueue();
        //消费者
        Thread t1=new Thread(()->{
            while (true){
                try {
                    int value = queue.take();
                    System.out.println("消费:"+value);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        //生产者
        Thread t2=new Thread(()->{
            int value=0;
            while (true){
                try {
                    System.out.println("生产:"+value);
                    queue.put(value);
                    //Thread.sleep(1000);
                    value++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        t1.start();
        t2.start();
    }
}

实现阻塞队列分为三步:

  1. 先实现一个普通队列
  2. 加上线程安全
  3. 加上阻塞功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/996337.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

制作立体图像实用软件:3DMasterKit 10.7 Crack

3DMasterKit 软件专为创建具有逼真 3D 和运动效果的光栅图片而设计&#xff1a;翻转、动画、变形和缩放。 打印机、广告工作室、摄影工作室和摄影师将发现 3DMasterKit 是一种有用且经济高效的解决方案&#xff0c;可将其业务扩展到新的维度&#xff0c;提高生成的 3D 图像和光…

企业架构LNMP学习笔记33

核心&#xff1a;负载均衡服务器有个转换&#xff0c;从外网转到内网的操作。返回的时候&#xff0c;从内网也要进行一次转换操作。 案例实现&#xff1a; 准备工作&#xff1a; ServerTypeIPserver04负载均衡调度服务器DS192.168.1.8&#xff08;对外访问的VIP&#xff09;&a…

网易Airtest全新推出:小型便携式集群解决方案!

1. 新旧版小型便携式集群大PK 先前我们针对中小型企业、工作室等&#xff0c;有推出过一款便携式机柜解决方案&#xff0c;业务同学只需要拎着一个像手提箱那么大的机柜&#xff0c;就可以在各个地方进行外场测试 &#xff0c;或者外出演示各种自动化场景。 但是之前的方案有…

ADC学习系列(一):ADC基础概念

本章主要是进行ADC的基础概念学习&#xff0c;从模拟和数字信号进行入手&#xff0c;分析各自的优缺点和应用场合&#xff0c;从而引出数模转换的重要性。紧接着提到了ADC部分最重要的奈奎斯特采样定理&#xff0c;了解采样频率和被测信号频率之间的关系。最后介绍了ADC的采样保…

领域驱动设计:DDD、中台和微服务的关系

文章目录 中台DDD、中台和微服务的协作模式中台建模 中台是抽象出来的业务模型&#xff0c;微服务是业务模型的系统实现&#xff0c;DDD作为方法论可以同时指导中台业务建模和微服务建设&#xff0c;三者相辅相成&#xff0c;完美结合。 中台 中台首先体现的是一种企业级的能力…

【Unity】rotation和Quaternion学习笔记

1.rotation 赋值 Quaternion可以为transform.rotation 赋值 2. 从正轴面向原点&#xff0c;顺时针旋转&#xff0c;角度正增加 正x轴面向原点&#xff0c;顺时针旋转&#xff0c;z正轴往下&#xff0c;rotation的x正增加。 3.rotation和Quaternion的关系 1.查询 2.实践 旋转…

基于SSM的精品酒销售管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

SpringAOP的使用总结

B站 【尚硅谷新版SSM框架全套视频教程&#xff0c;Spring6SpringBoot3最新SSM企业级开发】https://www.bilibili.com/video/BV1AP411s7D7?p47&vd_source726decf3eb63273901caae35ad437124 AOP即面向切面编程,通过使用一定的技术将非核心方法抽离出来,放入统一的类中进行…

关于 ogbg-molhi数据集的个人解析

cs224w_colab2.py这个图属性预测到底咋预测的 dataset.meta_info.T Out[2]: num tasks 1 eval metric rocauc download_name …

阿里云和腾讯云2核2G服务器价格和性能对比

2核2G云服务器可以选择阿里云服务器或腾讯云服务器&#xff0c;腾讯云轻量2核2G3M带宽服务器95元一年&#xff0c;阿里云轻量2核2G3M带宽优惠价108元一年&#xff0c;不只是轻量应用服务器&#xff0c;阿里云还可以选择ECS云服务器u1&#xff0c;腾讯云也可以选择CVM标准型S5云…

SpringBoot整合Redis 并 展示使用方法

步骤 引入依赖配置数据库参数编写配置类构造RedisTemplate创建测试类测试 1.引入依赖 不写版本号&#xff0c;也是可以的 在pom中引入 <!--redis配置--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-…

Kafka消费者组重平衡(一)

文章目录 概述消费者组特点什么是 Coordinator重平衡影响 概述 重平衡&#xff0c;也就是Rebalance, 就是让一个 Consumer Group 下所有的 Consumer 实例就如何消费订阅主题的所有分区达成共识的过程。在 Rebalance 过程中&#xff0c;所有 Consumer 实例共同参与&#xff0c;…

ShardingSphere分库分表(一):高性能架构模式

互联网业务兴起之后&#xff0c;海量用户加上海量数据的特点&#xff0c;单个数据库服务器已经难以满足业务需要&#xff0c;必须考虑数据库集群的方式来提升性能。高性能数据库集群的第一种方式是“读写分离”&#xff0c;第二种方式是“数据库分片”。 文章目录 1、读写分离架…

地理测绘基础知识(6) 照射距离等值线计算

上一篇文章中&#xff0c;我们采用HPR坐标系里的向量旋转&#xff0c;在地表绘制了这样的螺旋线&#xff1a; 在复杂多样的现实应用需求中&#xff0c;还有一种更为普遍的计算需求&#xff0c;就是求取地表到全向光源的距离为D的所有点的集合&#xff08;用多边形组成的近似椭…

MongoDB简介以及安装

文章目录 1. MongoDB简介2. NoSQL简介3. MongoDB安装 1. MongoDB简介 MongoDB是一种NoSQL数据库&#xff0c;采用了文档数据库模型。它以BSON&#xff08;Binary JSON&#xff09;格式存储数据&#xff0c;支持动态模式和灵活的查询语言。MongoDB具有以下特点&#xff1a; 文…

虚拟机 + Ubuntu22.04 + ros2 (humble) colcon build turtlebot3_node失败的解决方案

一、问题描述 在虚拟机Ubuntu22.04中安装了ROS2&#xff08;humble&#xff09;,下载turtlebot3。在colcon build --symlink-install 编译的过程中turtlebot3_Fake_node一直失败&#xff0c;无法正常运行&#xff0c;影响后面的仿真测试。 二、解决方案 查阅相关资料后发现问…

JAVA 从入门到起飞 面向对象 day08 P2

老师的知识点1 在JAVA中&#xff0c;必须先设计类&#xff0c;才能获得对象。 我的理解&#xff1a; 疑问&#xff1a;为什么是这样的呢&#xff1f; 答案&#xff1a; 在 JAVA 或其他面向对象的编程语言中&#xff0c;类是对象的蓝图或模板。这意味着在你创建对象之前&am…

【已解决】在Win11上离线安装 .NET Framework 3.5的方法【含网盘离线文件】

随 Windows 11提供的是.NET Framework 4.8&#xff0c;该环境可以运行任何 .NET Framework 4.x 应用。 而.NET Framework 3.5 支持为 .NET Framework 2.0 到 3.5 生成的应用&#xff0c;需要自行安装。 当Win11的应用软件需要.net framework3.5的运行环境时&#xff0c;就会提…

领域驱动设计:微服务架构模型

文章目录 整洁架构六边形架构DDD 分层架构三种微服务架构模型的对比和分析从三种架构模型看中台和微服务设计 整洁架构 整洁架构又名“洋葱架构”。为什么叫它洋葱架构&#xff1f;整洁架构的层就像洋葱片一样&#xff0c;它体现了分层的设计思想。在整洁架构里&#xff0c;同…

跨站请求伪造

CSRF是什么&#xff1f; 跨站请求伪造(Cross Site Request Forgery&#xff0c;CSRF)是一种攻击&#xff0c;它强制浏览器客户端用户在当前对其进行身份验证后的Web 应用程序上执行非本意操作的攻击&#xff0c;攻击的重点在于更改状态的请求&#xff0c;而不是盗取数据&#x…