【JavaEE】 阻塞式队列详解

文章目录

  • 🌲阻塞队列是什么
  • 🌳生产者消费者模型
    • 🚩耦合
      • 📌紧耦合(强耦合)
      • 📌松耦合(解耦合)
  • 🎄Java标准库中的阻塞队列的使用
    • 🚩标准库实现消费者生产者模型
  • 🍀阻塞队列的模拟实现
  • ⭕总结

🌲阻塞队列是什么

阻塞队列是一种特殊的队列. 也遵守 “先进先出” 的原则.
阻塞队列能是一种线程安全的数据结构, 并且具有以下特性:

  • 当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素.

  • 当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中插入元素.

阻塞队列的一个典型应用场景就是 “生产者消费者模型”. 这是一种非常典型的开发模型

🌳生产者消费者模型

在这里插入图片描述

生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。

那什么是耦合呢?

🚩耦合

耦合是两个或多个模块之间的相互关联。在软件工程中,两个模块之间的耦合度越高,维护成本越高。因此,在系统架构的设计过程中,应减少各个模块之间的耦合度,以提高应用的可维护性

耦合又分为紧耦合(强耦合)和 松耦合

📌紧耦合(强耦合)

紧耦合架构本质是Client/Server的模型,如下图所示
在这里插入图片描述
优点是:架构简单、设计简单、开发周期短、能够快速的开发、投入、部署、应用。

但随着集群规模的扩大,系统的稳定性逐渐变差,主要原因如下:

  • 同步操作导致对网络资源消耗大。同步操作在数据发送和数据返回之间,有很大一段是空闲的,这种空闲占用是对网络资源的极大浪费。

  • 安全控制力度差,因为服务器直接暴露给客户机,容易引发网络攻击行为。

  • 程序代码之间关联度过高,不利于模块化处理。

📌松耦合(解耦合)

松耦合架构本质上是在client/server模型之间加入一个代理,把CS模型变成CAS模型。 在新的架构下,客户机的角色不变,代理服务器承担起与客户机的通信,和对客户机的识别判断工作,服务器位于代理服务器后面,对客户机来说不可见,它只负责数据处理工作,另外我们也把CS模型的同步操作改为CAS的代理处理。 如下图所示:
在这里插入图片描述
优点如下:

  • 多任务并行处理能力获得极大提升。

  • 实现负载自适应机制(根据当时运行环境,松耦合架构分配并行工作任务,避免超载现象)。

  • 基本杜绝了对Server服务端的网络攻击行为,由于代理服务器的隔绝和筛查作用, 同时结合其它安全管理手段,外部攻击在代理服务器处就被识别和过滤掉了,这样就保护了后面的服务器不受影响。

  • 异步操作减少了网络资源消耗和操作关联。

  • 提高了系统的可维护性。

了解了耦合之后,我们就可以通过一个阻塞队列来实现一个生产者消费者的模型

生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取

在这个模型当中

  • 阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力.

比如在 “秒杀” 场景下, 服务器同一时刻可能会收到大量的支付请求. 如果直接处理这些支付请求,服务器可能扛不住(每个支付请求的处理都需要比较复杂的流程). 这个时候就可以把这些请求都放到一个阻塞队列中, 然后再由消费者线程慢慢的来处理每个支付请求.这样做可以有效进行 “削峰”, 防止服务器被突然到来的一波请求直接冲垮

削峰的作用在实现负载自适应机制(根据当时运行环境,松耦合架构分配并行工作任务,避免超载现象)。

  • 阻塞队列也能使生产者和消费者之间 解耦.

比如过年一家人一起包饺子. 一般都是有明确分工, 比如一个人负责擀饺子皮, 其他人负责包. 擀饺子皮的人就是 “生产者”, 包饺子的人就是 “消费者”.擀饺子皮的人不关心包饺子的人是谁(能包就行, 无论是手工包, 借助工具, 还是机器包), 包饺子的人也不关心擀饺子皮的人是谁(有饺子皮就行, 无论是用擀面杖擀的, 还是拿罐头瓶擀, 还是直接从超市买的).
在这里插入图片描述

🎄Java标准库中的阻塞队列的使用

在 Java 标准库中内置了阻塞队列. 如果我们需要在一些程序中使用阻塞队列, 直接使用标准库中的即可

使用注意事项:

  • BlockingQueue 是一个接口. 真正实现的类是有以下几种
    在这里插入图片描述

  • put 方法用于阻塞式的入队列, take 用于阻塞式的出队列

  • BlockingQueue 也有== offer, poll, peek 等方法, 但是这些方法不带有阻塞特性==

BlockingQueue<String> queue = new LinkedBlockingQueue<>();
// 入队列
queue.put("abc");
// 出队列. 如果没有 put 直接 take, 就会阻塞.
String elem = queue.take();

🚩标准库实现消费者生产者模型

这个实现比较简单,这里就直接上代码了

public class ThreadDemo1 {public static void main(String[] args) {BlockingDeque<Integer> blockingQueue = new LinkedBlockingDeque<>();Thread customer = new Thread(() -> {while(true) {try {int a = blockingQueue.take();System.out.println("消费元素为:" + a);} catch (InterruptedException e) {throw new RuntimeException(e);}}});Thread producer = new Thread(() -> {int n = 0;while(true) {try {System.out.println("生产元素为:" + n);blockingQueue.put(n++);Thread.sleep(500);} catch (InterruptedException e) {throw new RuntimeException(e);}}});customer.start();producer.start();}
}

运行结果如下:
在这里插入图片描述
我们可以看到基本上是成对出现的,生产一个,消费一个。趋于稳定

接下来我们自己模拟实现一个阻塞队列

🍀阻塞队列的模拟实现

这里我们又两种结构可以选择,一种是链表的,另一种是数组的形式实现

这里博主选择的是用数组的形式进行模拟实现

首先我们创建一个 “循环队列” ,关于循环队列了解的小伙伴,可以去看看博主相应的博客【数据结构】详解环形队列

这里只展示一个循环队列的代码:

public class MyBlockingQueue {private int[] items = new int[1000];private int head = 0;private int tail = 0;private int size = 0;// 入队列public void put(int value) {if (size == items.length) {return;}items[tail] = value;tail++;if (tail >= items.length) {tail = 0;}size++;}// 出队列public Integer take() {int result = 0;if (size == 0) {return null;}result = items[head];head++;if (head >= items.length) {head = 0;}size--;return result;}
}

上述代码只是一个简单的环形队列,如果在多线程中进行操作的话,会出现线程安全问题,所以接下来我们要做的是就是解决上述线程安全问题

  • 首先呢。我们要保证同一个对象,在出队列时不能入队列,在入队列时不能出队列

所以我们使用 synchronized 进行加锁控制

  • 其次。put 插入元素的时候, 判定如果队列满了, 就进行 wait. (注意, 要在循环中进行 wait. 被唤醒时不一
    定队列就不满了, 因为同时可能是唤醒了多个线程).take 取出元素的时候, 判定如果队列为空, 就进行 wait. (也是循环 wait)

所以我们在判断为满或者为空时,使用while循环进行判断

代码实现如下:

public class MyBlockingQueue {private int[] items = new int[1000];private int head = 0;private int tail = 0;private int size = 0;// 入队列public void put(int value) throws InterruptedException {synchronized (this) {while (size == items.length) {// 队列满了, 此时要产生阻塞.// return;this.wait();}items[tail] = value;tail++;if (tail >= items.length) {tail = 0;}size++;// 这个 notify 唤醒 take 中的 waitthis.notify();}}// 出队列public Integer take() throws InterruptedException {int result = 0;synchronized (this) {while (size == 0) {//return null;// 队列空, 也应该阻塞.this.wait();}result = items[head];head++;if (head >= items.length) {head = 0;}size--;// 唤醒 put 中的 waitthis.notify();}return result;}
}

测试代码如下:

public class ThreadDemo2 {public static void main(String[] args) {MyBlockingQueue queue = new MyBlockingQueue();Thread customer = new Thread(() -> {while (true) {try {int result = queue.take();System.out.println("消费: " + result);} catch (InterruptedException e) {e.printStackTrace();}}});customer.start();Thread producer = new Thread(() -> {int count = 0;while (true) {try {System.out.println("生产: " + count);queue.put(count);count++;Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}});producer.start();}
}

测试结果为:
在这里插入图片描述

⭕总结

关于《【软件测试】 初识软件测试》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

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

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

相关文章

大规模语言LLaVA:多模态GPT-4智能助手,融合语言与视觉,满足用户复杂需求

大规模语言LLaVA&#xff1a;多模态GPT-4智能助手&#xff0c;融合语言与视觉&#xff0c;满足用户复杂需求 一个面向多模式GPT-4级别能力构建的助手。它结合了自然语言处理和计算机视觉&#xff0c;为用户提供了强大的多模式交互和理解。LLaVA旨在更深入地理解和处理语言和视…

使用MFC创建一个SaleSystem

目录 1、项目的创建&#xff1a; 2、项目的配置&#xff1a; 3、设置窗口属性&#xff1a; &#xff08;1&#xff09;、设置图标 1&#xff09;、添加导入资源 2&#xff09;、代码初始化图标 &#xff08;2&#xff09;、设置标题 &#xff08;3&#xff09;、设置窗口…

如何解决香港服务器使用的常见问题

​  站长们在选择香港服务器租用时会考虑到它的各种性能以及稳定性&#xff0c;这是必须的。但是使用过程中还有些问题也不容忽视&#xff0c;比如&#xff1a;带宽资源是否短缺&#xff0c;是否存在安全漏洞&#xff0c;连接是否正常等这些问题也要考虑到。 香港服务器使用中…

整理uvc驱动相关函数的调用流程

目录 1、uvc_video.c初始化函数的调用关系 2、uvc_queue.c3、uvc_v4l2.c4、v4l2-core5、数据传输1、分配一个gadget请求2、请求一个queue 1、uvc_video.c // uvc_video.c uvc_video_encode_header uvc_video_encode_data uvc_video_encode_bulk uvc_video_encode_isoc uvcg_vi…

关闭mysql,关闭redis服务

1. 关闭redis服务&#xff1a; 查询redis安装目录&#xff1a; whereis redis which redis find / -name redis 关闭redis服务&#xff1a; redis-cli -h 127.0.0.1 -p 6379 auth 输入密码 shutdown 关闭redis服务 2. 关闭mysql服务&#xff1a; 查询mysql安装目录&…

Docker逃逸---SYS_PTRACE浅析

一、产生原因 用户授予了容器SYS_PTRACE权限&#xff0c;并且与宿主机共享一个进程命名空间(--pidhost)&#xff0c;使得容器内可以查看到宿主机的进程&#xff0c;攻击者可以利用进程注入&#xff0c;反弹shell&#xff0c;从而实现逃逸 二、利用条件 1、容器有SYS_PTRACE权…

(H5轮播)vue一个轮播里显示多个内容/一屏展示两个半内容

效果图 : html: <div class"content"><van-swipeclass"my-swipe com-long-swipe-indicator":autoplay"2500"indicator-color"#00C4FF"><van-swipe-itemclass"flex-row-wrap"v-for"(items, index) in M…

React +AntD + From组件重复提交数据(已解决)

开发场景&#xff1a; react Hooks andt 提交form表单内容给数据库(使用antd的form组件) 问题描述 提交是异步的&#xff0c;请提交方式是POST 方式 提交表单内容给后端&#xff0c;却产生了两次提交记录&#xff08;当然&#xff0c;数据新增了两条数据&#xff09;。可以…

VR虚拟展厅的亮点是什么?有哪些应用?

传统展厅主要是以静态陈列的形式来传达内容&#xff0c;而展示形式则有图片、视频等&#xff0c;虽然视频包含内容多&#xff0c;但是总体具有一定的局限性&#xff0c;客户体验感也较差&#xff0c;往往不能深入了解细节。随着VR技术越来越成熟&#xff0c;VR技术的广泛应用&a…

Qemu镜像安全加密测试

文章目录 简介1.已经过时的qemu自带的加密方式介绍1.1.创建secret uuid的xml1.2.产生uuid1.3.给secret赋值1.4.创建一个存储池1.5.在存储池中创建一个镜像1.6.在虚拟机中使用该镜像 2.弃用以上加密方式2.1.原作者Daniel Berrange的观点2.2.Markus Armbruster更深入的操作 3. LU…

在前端html页面中向服务器发送post登录请求

目录 前言 搭建服务器 搭建前端登录页面 获取表单值 使用axios发送post登录请求 前言 一般在html页面中向服务器发送post请求的模块为登录请求&#xff0c;本文将介绍如何向服务器发送post请求 搭建服务器 如何搭建服务器请看JWT认证这篇文章&#xff0c;有详细的解说。…

性能测试jmeter命令行运行+html测试报告解读

windows下打开jmeter的运行窗口&#xff0c;可以看到提示不要用GUI模式进行负载测试&#xff0c;如果要用负载测试&#xff0c;用cli模式&#xff0c;因为GUI模式运行jmeter比较消耗性能。 命令行模式 windows下找到jemeter所在文件夹&#xff0c;打开cmd输入命令。 jmeter -n…

Leetcode 第 365 场周赛题解

Leetcode 第 365 场周赛题解 Leetcode 第 365 场周赛题解题目1&#xff1a;2873. 有序三元组中的最大值 I思路代码复杂度分析 题目2&#xff1a;2874. 有序三元组中的最大值 II思路代码复杂度分析思路2 题目3&#xff1a;2875. 无限数组的最短子数组思路代码复杂度分析 题目4&a…

基于JAVA+SpringBoot+UniApp+Vue的前后端分离的手机移动端图书借阅平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着社会信息化的快速…

IPETRONIK数采与第三方软件集成

一 第三方软件 IPETRONIK公司提供IPEmotion用于车辆测试&#xff0c;但在某些特殊领域也有一些专业的软件&#xff0c;例如标定&#xff0c;则需要IPETRONIK数采来进行压力、温度、转速等信号的采集。 IPETRONIK提供了INCA和CANape插件&#xff0c;且这两款软件均可直接识别到…

微信小程序修改van-popup的背景颜色

效果图&#xff1a; van-popup背景颜色渐变 使用深度修改样式不生效&#xff0c;直接在 custom-style里面修改即可&#xff1b; <van-popup position"bottom"custom-style"height:25%;background:linear-gradient(95deg, #F8FCFF -0.03%, #EDF5FF 64.44…

【Qt之布局】QVBoxLayout、QHBoxLayout、QGridLayout、QFormLayout介绍及使用

在Qt中&#xff0c;布局管理器&#xff08;Layout&#xff09;用于管理窗口中的控件的位置和大小&#xff0c;以适应不同大小的窗口。 常用的布局管理器包括QVBoxLayout、QHBoxLayout、QGridLayout和QFormLayout。 先放张布局UI&#xff1a; 1. QVBoxLayout&#xff08;垂直布…

Linux性能优化--性能工具:磁盘I/O

6.0 概述 本章介绍的性能工具能帮助你评估磁盘I/O子系统的使用情况。这些工具可以展示哪些磁盘或分区已被使用&#xff0c;每个磁盘处理了多少I/O,发给这些磁盘的I/O请求要等多久才被处理。 阅读本章后&#xff0c;你将能够&#xff1a; 确定系统内磁盘I/O的总量和类型(读/写…

使用 ClickHouse 深入了解 Apache Parquet (一)

​ 【squids.cn】 全网zui低价RDS&#xff0c;免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 自2013年作为Hadoop的列存储发布以来&#xff0c;Parquet几乎已经成为一种无处不在的文件交换格式&#xff0c;它提供了高效的存储和检索。这种采纳使其成为更近期的…

为网站配置SSL

HTTPS &#xff08;全称&#xff1a;Hyper Text Transfer Protocol over SecureSocket Layer&#xff09;&#xff0c;是以安全为目标的 HTTP 通道&#xff0c;在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。HTTPS 在HTTP 的基础下加入SSL 层&#xff0c;HTTPS…