多线程---阻塞队列+生产者消费者模型

news2024/12/25 23:58:52

文章目录

  • 阻塞队列
    • 自己实现一个阻塞队列(三步)
    • 标准库中的阻塞队列
    • 使用阻塞队列的优势
  • 生产者消费者模型

阻塞队列

队列(Queue)是我们熟悉的一个数据结构,它是“先进先出”的。但是并不是所有的队列都是“先进先出”的,比如:
优先级队列(PriorityQueue):基于自己的比较规则,拿出相应的值。
消息队列(MQ):在队列中引入一个“类型”,出队列的时候会指定某个类型的元素先出。

而我们今天学习的阻塞队列,它是一个“先进先出”的队列,但又有一些其他特点:

  1. 线程安全的。
  2. 带有阻塞功能:
    如果队列满,继续入队列,入队列操作就会阻塞,直到队列不满,入队列操作才能完成。
    如果队列空,继续出队列,出队列操作就会阻塞,直到队列不空,出队列操作才能完成。

自己实现一个阻塞队列(三步)

  • 实现基本队列
class MyBlockingQueue{
    public int[] items = new int[100];
    public int head = 0;
    public int tail = 0;
    public int size = 0;

    //入队列
    public void put ( int key)  {
            // 插入操作
            items[tail] = key;

            tail++;

            if (tail >= items.length) {
                tail = 0;
            }

            size++;
        
    }


    //出队列
    public Integer take()  {
            // 删除操作
            int ret = items[head];
            head++;

            if (head >= items.length) {
                head = 0;
            }

            size--;
            
            return ret;
        
    }
}

  • 保证线程安全
class MyBlockingQueue{
    public int[] items = new int[100];
    public int head = 0;
    public int tail = 0;
    public int size = 0;

    //入队列

    public void put ( int key)  {
        synchronized (this) {
            // 插入操作
            items[tail] = key;

            tail++;

            if (tail >= items.length) {
                tail = 0;
            }

            size++;
        }
    }


    //出队列
    public Integer take()  {
        synchronized (this) {
            // 删除操作
            int ret = items[head];
            head++;

            if (head >= items.length) {
                head = 0;
            }

            size--;
           
            return ret;
        }
    }
}

  • 实现阻塞功能
class MyBlockingQueue{
    public int[] items = new int[100];
    public int head = 0;
    public int tail = 0;
    public int size = 0;

    //入队列

    public void put ( int key) throws InterruptedException {
        synchronized (this) {


            //当wait被唤醒之后 size还有可能为满 所以不能一唤醒了就直接去使用 得再次判断条件是否满足
            // 比如:1.抛出异常  2. 三个线程同时执行 其中两个线程竞争锁 没竞争到锁的线程被唤醒之后size还为空
            while(size >= items.length){
                this.wait();
            }

            //判断队列是否为满  满了不能插入 就阻塞
//            if (size >= items.length){
//                this.wait();
//            }

            // 插入操作
            items[tail] = key;

            tail++;

            if (tail >= items.length) {
                tail = 0;
            }

            size++;
            this.notify();

        }
    }


    //出队列
    public Integer take() throws InterruptedException {
        synchronized (this) {

            //当wait被唤醒之后 size还有可能为空 所以不能一唤醒了就直接去使用 得再次判断条件是否满足
            while(size <= 0){
                this.wait();
            }
            //判断队列是否为空 空了不能删除 就阻塞
//            if (size <= 0){
//                this.wait();
//            }

            // 删除操作
            int ret = items[head];
            head++;

            if (head >= items.length) {
                head = 0;
            }

            size--;
            this.notify();
            return ret;
        }
    }
}

标准库中的阻塞队列

    //标准库的阻塞队列
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<Integer> blockingQueue = new LinkedBlockingDeque<>(2);
        //带有阻塞功能的入队列
        blockingQueue.put(1);
        blockingQueue.put(2);
        blockingQueue.take();
        blockingQueue.put(3);

        //带有阻塞功能的出队列
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());

        blockingQueue.put(4);
        System.out.println(blockingQueue.take());

        blockingQueue.put(4);
    }

使用阻塞队列的优势

  • 有利于代码解耦合

在这里插入图片描述
在这里插入图片描述

  • 削峰填谷

在服务器A流量激增的情况下,通过阻塞队列能够进行限流。使服务器B、C、D能够不受干扰、平稳运行。

生产者消费者模型

生产者消费者模型:描述的是多线程协同工作的一种方式。借助阻塞队列实现。

	//生产者-消费者模型
    public static void main(String[] args) {
        MyBlockingQueue myBlockingQueue = new MyBlockingQueue();

        Thread thread = new Thread(() -> {
            int n = 1;
            while (true){
                try {
                    myBlockingQueue.put(n);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                n++;
            }
        });

        Thread thread1 = new Thread(() -> {
            while (true){
                try {
                    System.out.println(myBlockingQueue.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        thread.start();
        thread1.start();
    }

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

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

相关文章

椭圆曲线在SM2加解密中的应用(三)

一、SM2加密运算 1.1加密原始数据 SM2加密运算首先是用户A对数据加密,用户A拥有原始数据 椭圆曲线系统参数长度为klen比特的消息M公钥Pb椭圆曲线系统参数,已经在 椭圆曲线参数(二)中详细介绍;M就是需要加密消息,长度为klen; 1.1.1 公钥Pb的计算方式 公钥Pb=dBG,其中…

【MySQL--->复合查询】

文章目录 [TOC](文章目录) 一、基本查询二、多表查询三、自连接四、子查询1. 单行子查询2. 多行查询3.多列子查询4.在from语句中使用子查询5.合并查询 一、基本查询 查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的J 按照部门号升序而…

C++进阶篇3---二叉搜索树(Binary Search Tree)

一、二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 它的…

java之输入与输出的详细介绍

文章目录 输出的相关格式使用 Scanner 类进行控制台输入步骤&#xff1a;示例&#xff1a; 如何格式化输出&#xff1f;1. 使用 System.out.printf2. 使用 String.format printf与println 的区别printfprintln主要区别&#xff1a; 输出的相关格式 控制台输入是指通过命令行或…

JAVA中的垃圾回收器(2)------G1

一)G1垃圾回收器:-XX:UseG1GC:使用G1收集器 1)垃圾收集器迭代停顿时间越少越好&#xff0c;但是垃圾回收的总时间会增多&#xff0c;默认暂停时间默认是200ms&#xff0c;G1的内部底层算法非常复杂比CMS复杂&#xff0c;如果大内存&#xff0c;G1还比较有效果&#xff0c;但是如…

leetcode-数组

1.二分法手撕704&#xff08;诀窍在于用合法区间判断&#xff09;230810 左闭右闭: while(left<right)合法&#xff0c;middle(leftright)/2, if(nums[middle]>target)说明nums[middle]一定不是我们搜索的值&#xff0c;所以rightmiddle-1; elseif(nums[middle]<targe…

基于单片机的太阳跟踪系统的设计

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、设计的主要内容二、硬件电路设计2.1跟踪控制方案的选择2.1.1跟踪系统坐标系的选择2.2系统总体设计及相关硬件介绍…

9、电路综合-基于简化实频的任意幅频响应的微带电路设计

9、电路综合-基于简化实频的任意幅频响应的微带电路设计 网络综合和简化实频理论学习概述中的1-8介绍了SRFT的一些基本概念和实验方法&#xff0c;终于走到了SRFT的究极用途&#xff0c;给定任意响应直接综合出微带电路。 1、任意幅频响应的微带电路设计用途 我们演示了采用…

Flask基本教程以及Jinjia2模板引擎简介

flask基本使用 直接看代码吧&#xff0c;非常容易上手&#xff1a; # 创建flask应用 app Flask(__name__)# 路由 app.route("/index", methods[GET]) def index():return "FLASK&#xff1a;欢迎访问主页&#xff01;"if __name__ "__main__"…

【多线程面试题九】、说一说sleep()和wait()的区别

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;说一说sleep()和wait()的…

如何使用 Docker 搭建 Jenkins 环境?从安装到精通

不少兄弟搭 jenkins 环境有问题&#xff0c;有的同学用 window, 有的同学用 mac&#xff0c; 有的同学用 linux。 还有的同学公司用 window, 家里用 mac&#xff0c;搭个环境头发掉了一地。。。 这回我们用 docker 去搭建 jenkins 环境&#xff0c;不管你是用的是什么系统&…

方太描画未来厨房的模样

作者 | 辰纹 来源 | 洞见新研社 不知不觉中&#xff0c;iPhone已经更新到15代了&#xff0c;家里的电视变成了越来越轻薄的液晶屏&#xff0c;过去被称为“老三样”的富康&#xff0c;捷达、桑塔纳&#xff0c;如今也被以特斯拉为代表的新能源智能汽车们所取代…… 类似以上的…

第五章 I/O管理 一、I/O设备的基本概念和分类

目录 一、什么是I/O设备 1、定义&#xff1a; 2、按特性分类&#xff1a; 3、按传输速率分类&#xff1a; 4、按信息交换的方式分类&#xff1a; 二、总结 一、什么是I/O设备 1、定义&#xff1a; I/O设备就是可以将数据输入到计算机&#xff0c;或者可以接收计算机输出…

<C++> vector模拟实现

目录 前言 一、定义命名空间 二、构造函数 三、拷贝构造 四、赋值运算符重载 五、push_back && reserve 六、深拷贝问题 七、iterator 迭代器 1. 可读可写 2. 只读 八、operator[ ] 1. 可读可写 2. 只读 九、insert 问题&#xff1a;内部迭代器失效 十、erase 十一、re…

【网络安全】Seeker内网穿透追踪定位

Seeker追踪定位对方精确位置 前言一、kali安装二、seeker定位1、ngrok平台注册2、获取一次性邮箱地址3、ngrok平台登录4、ngrok下载5、ngrok令牌授权6、seeker下载7、运行seeker定位8、运行隧道开启监听9、伪装链接10、用户点击&#xff08;获取定位成功&#xff09;11、利用经…

(速进)完美解决“用户在命令行上发出了 EULAS_AGREED=1,表示不接受许可协议。”以及“此产品安装程序不支持降级”

安装VMware时候&#xff0c;出现以下两种情况的原因是&#xff1a;未彻底卸载&#xff08;之前安装过VMware&#xff09;&#xff0c;例如&#xff1a;还有相关配置信息、注册表信息等。只要彻底清理就可以解决此问题。 网上很多帖子使用了powershell里的命令 例如&#xff1…

Linux病毒疯狂增长,我们该如何…

导读国家信息中心日前与瑞星联合发布的《2017年上半年中国网络安全报告》&#xff08;以下简称《报告》&#xff09;指出&#xff0c;目前Linux系统病毒已快速增长。《报告》对2017年1至6月的网络安全现状与趋势进行统计、研究和分析后指出&#xff0c;Linux系统的勒索软件数量…

帆软finereport10.0 多个筛选框根据不同条件必须选一个才能查询

效果&#xff1a; 方法一&#xff1a; 方法二&#xff1a; 方法一&#xff1a;在查询里写上一段js&#xff0c;此方法会把端口和IP暴露出来&#xff0c;方法二比较完美。 var diff this.options.form.getWidgetByName("diff").getValue();//正反向 var fllh …

【多线程面试题 八】、说一说Java同步机制中的wait和notify

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;说一说Java同步机制中的…

Day 12 python学习笔记

模块 内置模块 sys模块 概述&#xff1a;Python 的 sys 模块提供访问解释器使用或维护的变量&#xff0c;和与解释器进行交互的函数。通俗来讲&#xff0c;sys 模块为程序与 Python 解释器的交互&#xff0c;提供了一系列的函数和变量&#xff0c;用于操控 Python 运行时的环境…