当前位置: 首页 > news >正文

多线程代码案例-阻塞队列

hi,大家好,今天为大家带来多线程案例--阻塞队列

这块知识点也很重要,要好好掌握呀~~~

                                 

🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸

                                             目录

                                💚1.什么是阻塞队列

                                💚2.生产者消费者模型

                                💚3标准库实现阻塞队列

                                💚4.自己实现一个阻塞队列

1.阻塞队列

我们之前在数据结构已经学了队列,什么是队列,我们来回忆一下,队列,是一种数据结构,先进先出.

阻塞队列也如此,先进先出,但是相比队列,它带有阻塞功能,当队列为满,要阻塞等待,当队列为空的时候,要阻塞等待.

因此,阻塞队列是线程安全的数据结构

当队列满的时候,会进入阻塞等待,直到有线程从队列取出元素

当队列空的时候,会进入阻塞等待,直到有线程在队列添加元素

阻塞队列的一个典型应用场景就是 "生产者消费者模型". 这是一种非常典型的开发模型.
需要我们重点掌握
2.生产者消费者模型
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题
举个简单的例子
包饺子的问题
一家四口人要包饺子
如果每个人擀一个皮,再包一个,这样就太低效了,如何包是最高效率的呢?
爸爸和大女儿作为生产者,(此处是生产饺子皮),包饺子皮,包好放到一个案板上,妈妈和小女儿一起包(此时是消费饺子皮)

 此时这个案板就是相当于一个阻塞队列

当饺子皮放满了,妈妈和小女儿就会告诉爸爸和大女儿先别擀面皮了,那么生产者就可以阻塞等待一会,当案板皮没了,爸爸和大女儿告诉消费者阻塞等待一会

那么这样做提高了线程执行效率

下面来说一说阻塞队列的好处

1.让代码块之间解耦合

啥是耦合呢,就是代码块和代码块之间的关联性的强弱

举个例子,当自己的好朋友生病了,作为好友,我需要去探望,那么如果是不相关的ABCD,那么我可以直接不管,我和我好友的耦合性就很高,相反,我和ABCD耦合性很低

说到这里,顺便说一下啥是内聚

内聚就是功能一样的代码放在一起,再举个例子,衣服要分门别类的放,就是相同的一类的要放在一起

我们写代码,要遵守"高内聚,低耦合"

我们再来举一个计算机的例子

 

 A服务器给B服务器发送请求,B服务器给A响应

服务器处理请求的时候,很耗费硬件资源,包括不限于(CPU,内存,硬盘,带宽)......

所以当某个硬件资源达到瓶颈,服务器就有挂的风险

假设请求量非常多,那么B回应不过来,B服务器很有可能就挂掉了,它俩耦合性就很高,那么A也就挂掉了

所以我们可以采用增加一个阻塞队列的方式

 

这样增加一个阻塞队列,降低了耦合性,B挂,不影响A


2.削峰填谷

1.削峰

还用这个例子,当A的请求很多的时候,会影响B的响应速率吗,答案是不会!

阻塞队列帮A承担了很多请求,让B保证平稳的速率响应请求,这就是削峰的意思

2.填谷:

当A需求猛增以后,迅速进入猛减期,此时会影响B响应速率吗,还是不会!

阻塞队列会自动调节,当 请求量突然骤减,阻塞队列会拿出之前积压的请求分配给B,这就是填谷


说完作用,差不多介绍完了,现在来看一看实现吧

3.标准库实现阻塞队列

采用BlockingQueue

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
//生产者消费者模型public class ThreadDemo3 {public static void main(String[] args) {BlockingQueue<Integer> queue=new LinkedBlockingQueue();//消费者Thread t1=new Thread(()->{while(true){try {int value=queue.take();System.out.println("消费"+value);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t1.start();//生产者Thread t2=new Thread(()->{int value=0;while(true){try {queue.put(value);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("生产"+value);value++;try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t2.start();}
}

标准库实现比较简单,我们自己实现就有难度了

4.自己实现阻塞队列

需要3步

1.实现一个普通队列

2.加上线程安全(加锁) 

3.增加阻塞等待功能

废话不多说,上代码

//自己实现阻塞队列class  MyBlockingQueue{volatile    private int[] items=new int[1000];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();}items[tail]=elem;tail++;if(tail==items.length){tail=0;}size++;this.notify();}synchronized   public Integer take() throws InterruptedException {if(size==0){//  return null;this.wait();}int value=items[head];head++;if(head==items.length){head=0;}size--;this.notify();return value;}}public class ThreadDemo2 {public static void main(String[] args) {MyBlockingQueue queue = new MyBlockingQueue();//消费者Thread t1 = new Thread(()->{while (true) {int value = 0;try {value = queue.take();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("消费" + value);}});t1.start();Thread t2=new Thread(()->{int value=0;while(true){try {queue.put(value);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("生产"+value);value++;try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t2.start();System.out.println("hello");}}

 解释:

 当队列满就阻塞等待,取出元素再唤醒,继续执行增加操作(如蓝色线)

 当队列空就阻塞等待,放进元素再唤醒,继续执行取出操作(如红色线)

在put和take方法上加上锁,保证原子性,线程安全

在这个操作中涉及到多次读以及修改操作,为了保证读取到的数据是正确的,也就会为了保证内存可见性,我们采用增加关键字volatile的操作

并且上述不可能同时wait,不可能有一个队列又空又满!!!

这里还有最后一个小问题

为啥要用while,不用if,?

 

看看wait的源码

wait可能会在线程执行过程中被提前唤醒,条件没成熟就醒了,这不符合代码逻辑,所以我们把if改为while,wait操作之前,发现条件不满足wait,等到wait被唤醒以后,再次判断wait唤醒是不是因为满足条件,不满足,就继续等待!!! 

以上就是今天的所有内容了,我们下期再见啦!!!

                    

 

相关文章:

多线程代码案例-阻塞队列

hi,大家好,今天为大家带来多线程案例--阻塞队列 这块知识点也很重要,要好好掌握呀~~~ &#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x…...

mysql的limit查询竟然有坑?

背景 最近项目联调的时候发现了分页查询的一个bug&#xff0c;分页查询总有数据查不出来或者重复查出。 数据库一共14条记录。 如果按照一页10条。那么第一页和第二页的查询SQL和和结果如下。 .png) 那么问题来了&#xff0c;查询第一页和第二页的时候都出现了11,12,13的记录…...

【Docker】MAC电脑下的Docker操作

文章目录安装Docker部署mysql 一主一从登录ChatGPT搞方案本地创建一个文件夹编辑docker-compose.yml文件启动检查并编排容器验证基于command的my.cnf配置的加载主数据库建一个用户给子数据库用于主从复制启动主从同步安装Docker 官网地址 https://www.docker.com/ 下载安装 验…...

【Python3】matplotlib,模块,进/线程,文件/xml,百度人脸api,hal/aiohttp/curl

文章目录1.matplotlib/时间复杂度/线性表&#xff1a;顺序表要求存储空间必须连续2.python模块导入&#xff1a;python3 -c ‘import sys;print(sys.path)’ 显示导入模块时会去哪些路径下查找3.进/线程&#xff1a;进/线程是不能随便创建&#xff0c;就像每招一个员工是有代价…...

异或相关算法

文章目录1. 异或的性质2. 题目一3. 题目二4. 题目三5. 题目四1. 异或的性质 我们知道&#xff0c;异或的定义是&#xff1a;相同为0&#xff0c;相异为1。所以也被称为无进位相加&#xff0c;根据这定义&#xff0c;我们可以得出三个性质&#xff1a; 1. N ^ N0。2. N ^ 0N。3…...

python 使用pyshp读写shp文件

安装 pip install pyshp 引入 import shapefile读取 sfshapefile.Reader("{路径名}",encodingutf-8) # 仅仅读取 shapes与shape shapessf.shapes() 返回值是一个列表&#xff0c;包含该文件中所有的”几何数据”对象shapesf.shape(0) Shape是第1个”几何数据”…...

eNSP FTP基础配置实验

关于本实验在本实验中&#xff0c;我们通过两台路由器来展示通过FTP在两台路由器之间传输文件。其中一台路由器AR2作为FTP服务器&#xff0c;另一台路由器AR1以FTP的方式登录AR2&#xff0c;并对AR2的文件系统进行一些更改。实验目的熟悉华为网络设备文件系统的管理。掌握华为网…...

堆及其多种接口与堆排序的实现

我们本期来讲解堆结构 目录 堆的结构 堆的初始化 堆的销毁 堆的插入 向上调整算法 堆的删除 向下调整算法 取堆顶元素 判断堆是否为空 堆中元素个数 堆排序 向下调整与向上调整效率计算 Top-K问题 全部代码 堆的结构 堆是一种用数组模拟二叉树的结构 逻辑结构是…...

JNI原理及常用方法概述

1.1 JNI(Java Native Interface) 提供一种Java字节码调用C/C的解决方案&#xff0c;JNI描述的是一种技术。 1.2 NDK(Native Development Kit) Android NDK 是一组允许您将 C 或 C&#xff08;“原生代码”&#xff09;嵌入到 Android 应用中的工具&#xff0c;NDK描述的是工具集…...

【Docker】之docker-compose的介绍与命令的使用

&#x1f341;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; 文章目录docker-compose简介docker-compose基础…...

水果新鲜程度检测系统(UI界面+YOLOv5+训练数据集)

摘要&#xff1a;水果新鲜程度检测软件用于检测水果新鲜程度&#xff0c;利用深度学习技术识别腐败或损坏的水果&#xff0c;以辅助挑拣出新鲜水果&#xff0c;支持实时在线检测。本文详细介绍水果新鲜程度检测系统&#xff0c;在介绍算法原理的同时&#xff0c;给出Python的实…...

flask多并发

多线程 flask默认使用多进程处理请求&#xff0c;因此&#xff0c;是支持并发的。比如两个调用a.html和b.html&#xff0c; 请求a.html未运行完成&#xff0c;在浏览访问b.html不会阻塞。开两个不同浏览器&#xff0c;分别请求请求运行时间较长的a.html也不阻塞。只要不用一个…...

我用Python django开发了一个商城系统,已开源,求关注!

起始 2022年我用django开发了一个商城的第三方包&#xff0c;起名为&#xff1a;django-happy-shop。当时纯粹是利用业余时间来开发和维护这个包&#xff0c;想法也比较简单&#xff0c;Python语言做web可能用的人比较少&#xff0c;不一定有多少人去关注&#xff0c;就当是一个…...

大数据项目之数仓相关知识

第1章 数据仓库概念 数据仓库&#xff08;DW&#xff09;: 为企业指定决策&#xff0c;提供数据支持的&#xff0c;帮助企业&#xff0c;改进业务流程&#xff0c;提高产品质量等。 DW的输入数据通常包括&#xff1a;业务数据&#xff0c;用户行为数据和爬虫数据等 ODS: 数据…...

RK3588平台开发系列讲解(视频篇)RTP H264 码流打包详解

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、单 NALU 封包方式二、组合封包方式三、分片封包方式沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 H264 码流是放在 RTP 的有效载荷部分的。因此有效载荷前面的 RTP 头部跟码流本身是没有关系的,所以我…...

realloc的补充 柔性数组

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C &#x1f525;座右铭&#xff1a;“不要等到什么都没有了&#xff0c;才下…...

【C语言】柔性数组

柔性数组1. 柔性数组介绍2. 柔性数组特点3. 用例3.1 代码一&#xff1a;3.2 代码二&#xff1a;4. 柔性数组优势&#xff1a;1. 柔性数组介绍 也许你从来没有听说过柔性数组&#xff08;flexible array&#xff09;这个概念&#xff0c;但是它确实是存在的。 C99 中&#xff0c…...

【Linux】权限详解

前言首先我们先来看一下权限的概念&#xff1a;在多用户计算机系统的管理中&#xff0c;权限&#xff08;privilege&#xff09;是指某个特定的用户具有特定的系统资源使用权力&#xff0c;像是文件夹&#xff0c;特定系统指令的使用或存储量的限制。通常&#xff0c;系统管理员…...

Android 之 打开相机 打开相册

Android 之 打开系统摄像头拍照 打开系统相册&#xff0c;并展示1&#xff0c;清单文件 AndroidManifest.xml<uses-permission android:name"android.permission.INTERNET" /><!--文件读取权限--><uses-permission android:name"android.permiss…...

C语言数据结构初阶(8)----栈与队列OJ题

CSDN的uu们&#xff0c;大家好。这里是C语言数据结构的第八讲。 目标&#xff1a;前路坎坷&#xff0c;披荆斩棘&#xff0c;扶摇直上。 博客主页&#xff1a; 姬如祎 收录专栏&#xff1a;数据结构与算法栈与队列的知识点我➡➡队列相关点我➡➡栈相关2. 用栈实现队列原题链接…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

深入解析 ReentrantLock:原理、公平锁与非公平锁的较量

ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...