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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Pyramidal Flow使用指南:快手、北大、北邮,开源可免费商用视频生成模型,快速上手教程

什么是 Pyramidal Flow? Pyramidal Flow 是由快手科技、北京大学和北京邮电大学联合推出的开源视频生成模型,它是完全开源的,发布在 MIT 许可证下,允许商业使用、修改和再分发。该模型能够通过文本描述生成最高10秒、分辨率为128…

铜业机器人剥片 - SNK施努卡

SNK施努卡有色行业电解车间铜业机器人剥片 铜业机器人剥片技术是针对传统人工剥片效率低下、工作环境恶劣及生产质量不稳定的痛点而发展起来的自动化解决方案。 面临人工剥片的诸多挑战,包括低效率、工作环境差、人员流动大以及产品质量控制不精确等问题。 人工剥片…

Idea基于JRbel实现项目热部署修改Java、Xml文件无需重启项目

Idea基于JRbel实现项目热部署修改Java、Xml文件无需重启项目 1.JRbel服务安装2.JRbel插件安装3.JRbel配置 1.JRbel服务安装 直接装插件的话,需要用到一个服务地址,服务下载链接:(现在没时间搞,会尽快加上)…

合合信息亮相PRCV大会,探讨生成式AI时代的内容安全与系统构建加速

一、前言 在人工智能技术的飞速发展下,生成式AI已经成为推动社会进步的重要力量。然而,随着技术的不断进步,内容安全问题也日益凸显。如何确保在享受AI带来的便利的同时,保障信息的真实性和安全性,已经成为整个行业待解…

Jmeter自动化实战

前言 由于系统业务流程很复杂,在不同的阶段需要不同的数据,且数据无法重复使用,每次造新的数据特别繁琐,故想着能不能使用jmeter一键造数据 创建录制模板 录制模板参考 首先创建一个录制模板 因为会有各种请求头,cookies,签名,认证信息等原因,导致手动复制粘贴的的全面导致接…

Flutter TextField和Button组件开发登录页面案例

In this section, we’ll go through building a basic login screen using the Button and TextField widgets. We’ll follow a step-bystep approach, allowing you to code along and understand each part of the process. Let’s get started! 在本节中,我们…

NVIDIA发布Nemotron-70B-Instruct,超越GPT-4o和Claude 3.5的AI模型

一、Nemotron-70B-Instruct 是什么 Nemotron-70B-Instruct 是由 NVIDIA 基于 Meta 的 Llama 3.1-70B 模型开发的先进大语言模型(LLM)。该模型采用了新颖的神经架构搜索(Neural Architecture Search,NAS)方法和知识蒸馏…

【华为HCIP实战课程二十】OSPF特殊区域NSSA配置详解,网络工程师

一、NSSA(Not So Stubby Area)区域 在NSSA区域内可以拥有ASBR,并且重分发进入OSPF的路由是以7类LSA形式存在,该类型的LSA只能存在于NSSA区域内不接收5类LSA,ABR过滤外部进入该区域的4 5类LSA,可以引入外部…

题解 力扣 LeetCode 739 每日温度 C++

题目传送门: 739. 每日温度 - 力扣(LeetCode)https://leetcode.cn/problems/daily-temperatures/description/ 思路: 就是单调栈的思路,具体见代码 不知道单调栈的,可以看我的这篇文章: 数…

web3对象如何连接以太网络节点

实例化web3对象 当我们实例化web3对象,我们一般开始用本地址,如下 import Web3 from web3 var web3 new Web3(Web3.givenProvider || ws://localhost:5173)我们要和以太网进行交互,所以我们要将’ws://localhost:5173’的本地地址换成以太…

【Linux学习】(6)编译器gcc/g++

前言 本节重点:掌握gcc/g编译器的使用,并了解其过程,原理 一、Linux编译器-gcc/g使用 1. gcc/g的基本使用 在前面我们学习了vim,知道如何在Linux中编写代码。但又是如何编译代码的?——在Linux中我们编译代码使用的是…

UDP(用户数据报协议)端口监控

随着网络的扩展,确保高效的设备通信对于优化网络功能变得越来越重要。在这个过程中,端口发挥着重要作用,它是实现外部设备集成的物理连接器。通过实现数据的无缝传输和交互,端口为网络基础设施的顺畅运行提供了保障。端口使数据通…

Linux中安装配置SQLite3,并实现C语言与SQLite3的交互。

前言 SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。本次实验介绍在Linux上实现C语言和SQLite3的交互,利用C语言编写相关语句,连接数据库、操作数…

【数据结构初阶】二叉树---堆

二叉树-堆的实现 一、树的概念(什么是树)二、二叉树的概念及结构2.1 二叉树的概念2.2 二叉树的性质2.3 二叉树存储结构 三、二叉树的顺序结构3.1 堆的概念及结构3.2 堆的向下调整算法3.3堆的创建 四、堆的代码实现4.1 堆的初始化4.2 堆的销毁4.3 堆的插入…

如何从iconfont中获取字体图标并应用到微信小程序中去?

下面我们一一个微信小程序的登录界面的制作为例来说明,如何从iconfont中获取字体图标是如何应用到微信小程序中去的。首先我们看效果。 这里所有的图标,都是从iconfont中以字体的形式来加载的,也就是说,我们自始至终没有使用一张…

jenkins 自动化部署Springboot 项目

一、安装docker 1.更新yum命令 yum -y update2.查看机器有残留的docker服务,有就卸载干净 查看docker 服务 rpm -qa |grep docker卸载docker sudo yum remove docker-ce docker-ce-cli containerd.io sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/contai…

linux下的进程等待(wait、waitpid)

目录 引言 进程等待的必要性 见见猪跑:是什么 怎么办 多个子进程时 阻塞等待 非阻塞轮询 参数一: 参数二 进程等待的原理 进程退出相关的宏 第三个参数option(设置等待的方式) 引言 在Linux操作系统中,进程…

Jmeter实际应用

环境准备 JDK1.8Jmeter 5.6.3 下载地址Jmeter 插件 下载地址 放到lib/ext下 常用命令 # 启动 sh jmeter# 集群模式下启动节点,不启动用不了集群 sh jmeter-server#生成ssl需要的证书, 这里会要求输入个密码,是要在jmeter中用的 keytool -import -ali…

Claude Financial Data Analyst:基于Claude的金融数据分析工具!免费开源!

大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,专注于分享AI全维度知识,包括但不限于AI科普,AI工…

基于SSM+小程序的垃圾分类管理系统(垃圾2)

👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM小程序的垃圾分类管理系统实现了管理员及用户。 1、管理员功能结构图,管理员功能有个人中心,管理员管理,基础数据管理、论坛管理、垃圾信息管理…