JavaEE----多线程(四)----阻塞队列的介绍和初步实现

文章目录

  • 1.阻塞队列
    • 1.1作用一:解耦合
    • 1.2作用二:削峰填谷
    • 1.3系统里面的阻塞队列的使用
    • 1.4实现普通队列
    • 1.5在普通队列的基础上面实现阻塞队列
    • 1.6设计优化
    • 1.7实现初步的生产者消费者模型

1.阻塞队列

阻塞队列的最大意义:就是实现==“生产者消费者模型”==-----一个常见的多线程代码编写方式

第一个主要的特点就是:解耦合(减少模块之间的影响程度);

1.1作用一:解耦合

对于下面的这个服务器端和客户端之间进行交互的时候,我们原本的这个服务器只有这个B(没有和客户端直接进行交互的),我们的服务器A是直接和我们的用户进行交互的,我们的服务器A收到的这个消息就会发送给我们的服务器B,当我们的这个服务器B扛不动的时候,就会多出一个服务器C进行这个分担;

image-20241025100128176

该模式下面存在的两个问题:

1.如果我们的这个服务器B出现了问题,这个时候服务器A可能会受到影响,因为两者之间是进行信息的发送和响应的,因此两个之间可能会受到彼此的影响;

对于上面的这个存在的问题,我们的解决方式就是创建阻塞队列,我们的这个服务器A接收到的这个客户端的访问数据就会被我们的这个服务器A直接存放到这个阻塞队列里面去,而不会直接和我们的这个服务器BC进行交互,我们的服务器BC从这个阻塞队列里面进行数据的读取,这样的话就不会直接和我们的BC服务器进行交互,减少这个耦合度;

1.2作用二:削峰填谷

下面的这个就是我们的客户端和服务器端之间的交互的情况,我们的这个服务器A接受多少的这个用户的访问量,就会发送给这个BC,但是如果这个BC的性能之类的没有这么强,这个时候可能就会出现服务器的崩溃的问题

image-20241025095805576

对于上面的这个现象,我们的解决方案也是下面的这个阻塞队列,因为这个阻塞队列相当于就是一个缓冲的平台,我们的这个消息量不可能一直很大,

削峰---------当我们的这个消息量很大的时候,这个时候就是峰,我们的这个阻塞队列削峰就是体现在让这个数据量存下来,以这个服务器BC可以接受的方式进行获取;

填谷---------当我们的这个请求量不是很大的时候,我们的这个阻塞队列里面的这个内容就会持续的进行输出,让我们的这个服务器BC进行处理,这样就不至于我们的这个服务器BC忙的时候特别忙,请求量不大的时候特别悠闲,这个就是削峰填谷的效果的体现;

image-20241025170414173

1.3系统里面的阻塞队列的使用

下面的这个我们是使用到了这个阻塞队列里面的这个put和take方法去进行这个队列里面的元素的进入和数据的出队列,但是我们的这个入队列的时候只进去3个数据,但是我们出队列的时候调用了4次这个take方法;

这个时候我们运行程序,就会发现这个前面的三次取出来数据的时候,是没有问题的,但是轮到这个第四次的时候,因为这个队列这个时候里面已经没有数据了,这个时候就会发生这个阻塞的现象;

image-20241023214954614

1.4实现普通队列

我们想要实现的就是下面的这个类似的环形队列,在这个队列里面为了计数(判断这个队列是满的还是空的),我们使用一个空间进行统计数量(因为如果不这样做的话,无论是满的还是空的,这个时候我们的这个tail都是和这个head指向相同的位置的)

image-20241024133329270

下面的是整体架构:

我们首先对于这个过程中会使用到的变量进行定义,例如下面的这个head和tail分别用来表示我们的这个环形数组的第一个元素和最后的一个元素,size表示这个队列里面当前是有多少个元素

image-20241023220028706

分别实现两个方法:

put是向这个队列里面去放入数据,我们首先需要判断这个队列是不是满的,如果是满的这个时候直接返回即可,因为这个时候我们是不可以往这个队列里面去插入元素的;

如果没有满,因为我们的这个tail就是最后一个元素的下一个位置,这个时候我们直接把这个tail位置放进去一个元素即可;

take是从这个队列里面拿数据,就是队列里面的数据出队列的过程,首先判断size==0就是这个队列里面是不是有数据,如果这个时候是有数据的,我们的这个取出来的数据就是队头的数据,因此我们使用这个ret变量把这个head指向的这个第一个队列元素记录下来,然后把这个ret作为我们的返回值,然后把这个head++,接着把这个size–即可,无论是上面的put还是下面的这个take,我们最后是一定需要对于这个size进行更新的;

image-20241023220132016

1.5在普通队列的基础上面实现阻塞队列

首先出于对这个线程安全的考虑,我们使用这个synchronized关键字进行修饰,这样可以避免一个线程进行操作的时候另外一个线程的介入;

image-20241025171907841

实现阻塞:使用wait和notify方法:

下面的这个代码里面,我们加入了这个wait和notify,分别表示的就是线程的阻塞和这个线程的等待;

下面的是两个方法里面的这个wait和notify方法的使用,其实这个是彼此相互作用的 ;

我们的这个put是添加数据的,当我们的这个size==data.length的时候,我们就不可以继续添加数据了,这个时候使用这个wait进行阻塞,但是什么时候唤醒呢?就是我们的这个take方法里面的这个size–之后,这个时候我们的这个队列里面多出来空余的位置,这个时候我们就可以唤醒这个等待,向这个队列继续添加元素;

同理,我们的这个队列本来就是空的时候,我们的这个take方法里面需要进行这个wait操作,这个时候也是被阻塞,当我们的这个put里面的这个size++之后,就是这个队列里面有了新的元素,这个时候我们在唤醒这个阻塞的队列,进行这个take的相关的实现;

image-20241025173453632

1.6设计优化

但是这个依然是存在问题的,就是例如我们的这个put方法里面,是进行这个数据的放入的,但是如果我们的这个线程除了被这个notify唤醒,其实是存在被这个interrupt中断的,就是这个wait阻塞的时候因为这个interrupt而被停止这个休眠的过程,这个时候其实是可以使用我们的throws出来的异常处理的;

但是这个时候,如果因为异常被终止,这个时候我们的这个队列还是满的,我们的这个时候使用这个data[tail]=elem方法其实不可以,因为我们的这个队列还是满的,只不过这个interrupt把这个过程结束了;

因此我们进行下面的这个优化,就是wait停止之后再次判断这个队列是不是满的,为了高效,我们使用这个while就可以满足这样的需求:

image-20241025174307471

1.7实现初步的生产者消费者模型

下面的这个就是在主方法里面进行操作,我们上面的都是在这个自定义的这个类里面进行操作的;

现在我们在这个主方法里面是创建了两个线程,生产者是创建一次这个元素就会进行休眠,我们的这个消费者不会进行休眠,因此这时候就是我们的生产者生产一个,我们的消费者就消费一个;(下面的这个代码里面应该是Thread.sleep而不是这个下面写的t1)

image-20241025230942640

下面的这个就是执行的情况:

image-20241025231910635

下面,我们让这个生产者不休眠,让这个消费者休眠:

image-20241025232506784

这个时候的情况就是我们的这个生产者会生产出来大量的数据,但是我们的这个消费者进行处理的时候会休眠,因此刚开始会产生大量的数据,但是后来就不会产生很多了;

我们可以看到,刚开始会生产1000数据,但是我们处理很慢,因此1000之后我们的这个生产速率就会放慢的,基本上就是一次1~2个的样子;

image-20241025232711908

除此之外,为了防止这个线程的交叉执行,我们可以给这个变量加上这个volatile关键字:

image-20241025233042289

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

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

相关文章

js 鼠标拖动canvas画布

功能点&#xff1a; 鼠标拖拽canvas画布移动鼠标检测rect鼠标检测circle 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-sc…

SQL 干货 | SQL 半连接

大多数数据库开发人员和管理员都熟悉标准的内、外、左和右连接类型。虽然可以使用 ANSI SQL 编写这些连接类型&#xff0c;但还有一些连接类型是基于关系代数运算符的&#xff0c;在 SQL 中没有语法表示。今天我们将学习一种这样的连接类型&#xff1a;半连接&#xff08;Semi …

PyTorch 中 12 种张量操作详解

创作不易&#xff0c;还请各位同学三连点赞&#xff01;&#xff01;收藏&#xff01;&#xff01;转发&#xff01;&#xff01;&#xff01; 对于刚入门学习Python还找不到方向的小伙伴可以试试我的这份学习方法和籽料&#xff0c;免费自取&#xff01;&#xff01; PyTorc…

后台管理员登录实现--系统篇

我的小系统后台原来就有一个上传图片的功能还夹带个删除图片的功能&#xff0c;还嵌到了一个菜单里面。之前效果如下 那么现在为了加大安全力度&#xff0c;想增加一个登录页面。通过登录再到这个页面。看着貌似很简单&#xff0c;但是听我细细说来&#xff0c;要新增些什么东西…

机器学习——元学习(Meta-learning)

元学习&#xff08;Meta-learning&#xff09;&#xff1a;学习如何学习的机器学习 元学习&#xff08;Meta-learning&#xff09;&#xff0c;即“学习如何学习”&#xff0c;是机器学习领域中一个令人兴奋且极具潜力的研究方向。它的核心目标是让机器学习系统学会高效地学习…

海港[NOIP2016]

题目描述 小 K 是一个海港的海关工作人员&#xff0c;每天都有许多船只到达海港&#xff0c;船上通常有很多来自不同国家的乘客。 小 K 对这些到达海港的船只非常感兴趣&#xff0c;他按照时间记录下了到达海港的每一艘船只情况&#xff1b;对于第 i 艘到达的船&#xff0c;他…

C#第四讲:C#语言基本元素概览,初识类型、变量与方法,算法简介

一、构成C#语言的基本元素 1、标识符 允许将下划线用作初始字符(这是C编程语言的传统)。 允许在标识符中使用 Unicode 转义序列&#xff0c;以及允许“”字符作为前缀以使关键字能够用作标识符。 &#xff08;1&#xff09;命名方法 变量名&#xff1a;用驼峰法。&#xff…

【SQL实验】表的更新和简单查询

完整代码在文章末尾 在上次实验创建的educ数据库基础上&#xff0c;用SQL语句为student表、course表和sc表中添加以下记录 【SQL实验】数据库、表、模式的SQL语句操作_创建一个名为educ数据库,要求如下: (下面三个表中属性的数据类型需要自己设计合适-CSDN博客在这篇博文中已经…

安全见闻---清风

注&#xff1a;本文章源于泷羽SEC&#xff0c;如有侵权请联系我&#xff0c;违规必删 学习请认准泷羽SEC学习视频:https://space.bilibili.com/350329294 安全见闻1 泷哥语录&#xff1a;安全领域什么都有&#xff0c;不要被表象所迷惑&#xff0c;无论技术也好还是其他方面…

YoloV9改进策略:主干网络改进|DeBiFormer,可变形双级路由注意力|全网首发

摘要 在目标检测领域,YoloV9以其高效和准确的性能而闻名。然而,为了进一步提升其检测能力,我们引入了DeBiFormer作为YoloV9的主干网络。这个主干网络的计算量比较大,不过,上篇双级路由注意力的论文受到很大的关注,所以我也将这篇论文中的主干网络用来改进YoloV9,卡多的…

[jeecg-boot] vue3 版本 nvm 下载node版本

安装pnpm 使用cnpm 进行下载依赖

JavaWeb 23.一文速通npm的配置和使用

目录 一、npm的介绍 二、npm的安装和配置 1.安装 &#xff1a; 2.配置依赖下载使用阿里镜像 3. 配置全局依赖下载后存储位置 4.升级npm版本 5.环境变量配置 三、npm常用命令 1.项目初始化 npm.init npm init -y 2.安装依赖文件 3. 升级依赖 4.卸载依赖 5.查看依赖 查看项目…

深入浅出 Vue3 nextTick

程序员节日快乐~ #1024程序员节 | 征文# nextTick 概念 当你在 Vue 的响应式数据模型中对数据进行修改时&#xff0c;这些变化并不会立即同步到 DOM 上_&#xff0c;而是会在当前的微任务队列&#xff08;microtask queue&#xff09;执行完毕后进行批量更新。这种机制被称为…

内网穿透:如何借助Cloudflare连接没有公网的电脑的远程桌面(RDP)

内网穿透&#xff1a;如何借助Cloudflare连接没有公网的电脑的远程桌面(RDP)-含详细原理配置说明介绍 前言 远程桌面协议(RDP, Remote Desktop Protocol)可用于远程桌面连接&#xff0c;Windows系统&#xff08;家庭版除外&#xff09;也是支持这种协议的&#xff0c;无需安装…

使用 NumPy 和 Matplotlib 实现交互式数据可视化

使用 NumPy 和 Matplotlib 实现交互式数据可视化 在数据分析中&#xff0c;交互式可视化可以更好地帮助我们探索和理解数据。虽然 Matplotlib 是静态绘图库&#xff0c;但结合一些技巧和 Matplotlib 的交互功能&#xff08;widgets、event handlers&#xff09;&#xff0c;我…

UE5里的TObjectPtr TSharedPtr TWeakPtr有什么区别

在 Unreal Engine&#xff08;UE&#xff09;编程中&#xff0c;TObjectPtr、TSharedPtr 和 TWeakPtr 都是 指针类型&#xff0c;但它们在生命周期管理和使用场景上有不同的特点。让我们详细分析这些指针的区别和用途。 TObjectPtr TObjectPtr 是 UE5 中引入的新智能指针类型…

水轮发电机油压自动化控制系统解决方案介绍

在现代水电工程中&#xff0c;水轮机组油压自动化控制系统&#xff0c;不仅直接关系到水轮发电机组的安全稳定运行&#xff0c;还影响着整个水电站的生产效率和经济效益。 一、系统概述 国科JSF油压自动控制系统&#xff0c;适用于水轮发电机组调速器油压及主阀&#xff08;蝶…

Dongle Sentinal在Jenkins下访问不了的问题

背景&#xff1a; 工作站部署的jenkins的脚本无法正常打包&#xff0c;定位后发现是本地获取不了license&#xff0c;但是使用usb over network的远程license都能获取并正常打包 分析&#xff1a; 获取不了license的原因是本地无法识别dongle。根据提供信息&#xff0c;之前…

SAP_SD模块-销售订单创建价格扩大10倍问题分析及后续订单价格批量更新问题处理

一、业务背景 我们公司的销售订单&#xff0c;是通过第三方销售管理平台创建好订单后&#xff0c;把表头和行项目数据&#xff0c;定时推送到SAP&#xff1b;SAP通过自定义表ZZT_ORDER_HEAD存放订单表头数据&#xff0c;通过ZZT_ORDER_DETAIL存放行项目数据&#xff1b;然后再用…

深入探讨 HTTP 请求方法:GET、POST、PUT、DELETE 的实用指南

文章目录 引言GET 方法POST 方法PUT 方法DELETE 方法小结适用场景与特点总结最佳实践 在 API 设计中的重要性 引言 HTTP 协议的背景&#xff1a;介绍 HTTP&#xff08;超文本传输协议&#xff09;作为互联网的基础协议&#xff0c;自 1991 年发布以来&#xff0c;成为客户端和…