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

【基础篇】7 # 队列:队列在线程池等有限资源池中的应用

说明

【数据结构与算法之美】专栏学习笔记

什么是队列?

队列是一种操作受限的线性表数据结构,特点是先进先出,最基本的操作有:入队 enqueue(),放一个数据到队列尾部;出队 dequeue(),从队列头部取一个元素。

在这里插入图片描述

顺序队列和链式队列

  • 用数组实现的队列叫作顺序队列
  • 用链表实现的队列叫作链式队列

基于数组的队列实现方法

队列需要两个指针:

  • 一个是 head 指针,指向队头;
  • 一个是 tail 指针,指向队尾。

用 Java 语言实现:


// 用数组实现的队列
public class ArrayQueue {// 数组:items,数组大小:nprivate String[] items;private int n = 0;// head表示队头下标,tail表示队尾下标private int head = 0;private int tail = 0;// 申请一个大小为capacity的数组public ArrayQueue(int capacity) {items = new String[capacity];n = capacity;}// 入队操作,将item放入队尾public boolean enqueue(String item) {// tail == n表示队列末尾没有空间了if (tail == n) {// tail ==n && head==0,表示整个队列都占满了if (head == 0) return false;// 数据搬移for (int i = head; i < tail; ++i) {items[i-head] = items[i];}// 搬移完之后重新更新head和tailtail -= head;head = 0;}items[tail] = item;++tail;return true;}// 出队public String dequeue() {// 如果head == tail 表示队列为空if (head == tail) return null;// 为了让其他语言的同学看的更加明确,把--操作放到单独一行来写了String ret = items[head];++head;return ret;}
}

当 tail 移动到最右边,即使数组中还有空闲空间,也无法继续往队列中添加数据,针对这种情况,只需要在入队时,再集中触发一次数据的搬移操作。示意图如下:

在这里插入图片描述

基于链表的队列实现方法

  • 入队时:tail->next= new_nodetail = tail->next
  • 出队时:head = head->next

入队出队示意图:

在这里插入图片描述

/*** 基于链表实现的队列。** Author: nameczz*/class Node {constructor(element) {this.element = elementthis.next = null}
}export class QueueBasedOnLinkedList {constructor() {this.head = nullthis.tail = null}enqueue(value) {if (this.head === null) {this.head = new Node(value)this.tail = this.head} else {this.tail.next = new Node(value)this.tail = this.tail.next}}dequeue() {if (this.head !== null) {const value = this.head.elementthis.head = this.head.nextreturn value} else {return -1}}
}
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>07.基于链表实现的队列</title></head><body><script type="module">import { QueueBasedOnLinkedList } from './js/07/QueueBasedOnLinkedList.js';const newQueue = new QueueBasedOnLinkedList();// 元素入队newQueue.enqueue(1);newQueue.enqueue(2);newQueue.enqueue(3);console.log('入队--->', newQueue);// 获取元素let res = 0;console.log("-------获取dequeue元素------");while (res !== -1) {res = newQueue.dequeue();console.log(res);}</script></body>
</html>

在这里插入图片描述

循环队列

循环队列就是普通队列首尾相连形成了一个环。

比如:下面队列的大小为 8,当前 head=4,tail=7。

在这里插入图片描述

当有一个新的元素 a 入队时,放入下标为 7 的位置。将 tail 更新为 0 ,而不是 8。

如何判断循环队列队空和队满呢?

  • 队空:队列为空的判断条件是 head == tail
  • 队满:当队满时,(tail + 1)%n = head

基于数组的循环队列实现方式

public class CircularQueue {// 数组:items,数组大小:nprivate String[] items;private int n = 0;// head表示队头下标,tail表示队尾下标private int head = 0;private int tail = 0;// 申请一个大小为capacity的数组public CircularQueue(int capacity) {items = new String[capacity];n = capacity;}// 入队public boolean enqueue(String item) {// 队列满了if ((tail + 1) % n == head) return false;items[tail] = item;// 取余运算保证,数组队列的循环插入效果tail = (tail + 1) % n;return true;}// 出队public String dequeue() {// 如果head == tail 表示队列为空if (head == tail) return null;String ret = items[head];// 因为要保持一个环状,必须通过取余运算才能得到保障!head = (head + 1) % n;return ret;}
}

基于链表实现的循环队列

/*** 基于链表实现的循环队列。** Author: nameczz*/class Node {constructor(element) {this.element = elementthis.next = null}
}export class CircularQueue {constructor() {this.head = nullthis.tail = null}// 入队enqueue(value) {if (this.head === null) {this.head = new Node(value)this.head.next = this.headthis.tail = this.head} else {const flag = this.head === this.tailthis.tail.next = new Node(value)this.tail.next.next = this.headthis.tail = this.tail.nextif (flag) {this.head.next = this.tail}}}// 出队dequeue() {if(this.head == null) return -1if (this.head === this.tail) {const value = this.head.elementthis.head = nullreturn value} else {const value = this.head.elementthis.head = this.head.nextthis.tail.next = this.headreturn value} }display() {let res = 0console.log('-------获取dequeue元素------')while (res !== -1) {res = this.dequeue()console.log(res)}}
}
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>07.基于链表实现的循环队列</title></head><body><script type="module">import { CircularQueue } from "./js/07/CircularQueue.js";const newCircularQueue = new CircularQueue();// 插入元素newCircularQueue.enqueue(1);newCircularQueue.enqueue(2);newCircularQueue.enqueue(3);console.log(newCircularQueue);// 获取元素newCircularQueue.display();newCircularQueue.enqueue(1);newCircularQueue.display();</script></body>
</html>

在这里插入图片描述

阻塞队列

阻塞队列就是在队列基础上增加了阻塞操作。

  • 在队列为空的时候,从队头取数据会被阻塞。直到队列中有了数据才能返回
  • 如果队列已经满了,那么插入数据的操作就会被阻塞。直到队列中有空闲位置后再插入数据,然后再返回

可以使用阻塞队列实现一个生产者 - 消费者模型,有效地协调生产和消费的速度。

如何实现一个线程安全的队列呢?

线程安全的队列叫作并发队列。在多线程情况下,会有多个线程同时操作队列,这个时候就会存在线程安全问题,最简单的解决方式就是直接在 enqueue()、dequeue() 方法上加锁,但是锁粒度大并发度会比较低,同一时刻仅允许一个存或者取操作。

如何实现一个高效的并发队列:

  1. 基于数组的循环队列:避免数据搬移
  2. CAS原子操作:避免真正的去OS底层申请锁资源

队列的应用

基于链表的实现方式,可以实现一个支持无限排队的无界队列(unbounded queue),但是可能会导致过多的请求排队等待,请求处理的响应时间过长。所以,针对响应时间比较敏感的系统,基于链表实现的无限排队的线程池是不合适的。而基于数组实现的有界队列(bounded queue),队列的大小有限,所以线程池中排队的请求超过队列大小时,接下来的请求就会被拒绝,这种方式对响应时间敏感的系统来说,就相对更加合理。

队列可以应用在任何有限资源池中,用于排队请求,比如数据库连接池等。对于大部分资源有限的场景,当没有空闲资源时,基本上都可以通过队列这种数据结构来实现请求排队。

相关文章:

【基础篇】7 # 队列:队列在线程池等有限资源池中的应用

说明 【数据结构与算法之美】专栏学习笔记 什么是队列&#xff1f; 队列是一种操作受限的线性表数据结构&#xff0c;特点是先进先出&#xff0c;最基本的操作有&#xff1a;入队 enqueue()&#xff0c;放一个数据到队列尾部&#xff1b;出队 dequeue()&#xff0c;从队列头…...

matlab进行双目标定获取双目参数并打印教程

文章目录前言1.打开matlab进行双目标定2.获取想要的参数前言 在相同的标定算法和标定参数下&#xff0c;Python和Matlab的标定精度是相同的。因为标定精度主要取决于标定算法和标定参数的质量&#xff0c;而不是编程语言的选择。 不同的编程语言可能使用不同的库或实现细节&…...

JVM类加载机制

回到2018年的抖音哈哈. 回顾下&#xff1a; java开发环境: java编译运行过程: 1) 编译期&#xff1a;.java源文件&#xff0c;经过编译&#xff0c;生成.class字节码文件 2) 运行期&#xff1a;JVM加载.class并运行.class(0和1) 特点: 跨平台、一次编程,处处报错 名词解释: 1…...

8.1 优化概述

数据库性能取决于数据库级别的几个因素&#xff0c;例如表、查询和配置设置。这些软件结构导致了硬件级别的 CPU 和 I/O 操作&#xff0c;您必须将其最小化并尽可能提高效率。在研究数据库性能时&#xff0c;首先要学习软件端的高级规则和准则&#xff0c;然后使用墙上的时钟时…...

从0到1一步一步玩转openEuler--14 openEuler DNF(YUM)配置管理

文章目录14.1 DNF配置文件14.1.1 配置main部分14.1.2 配置repository部分14.1.3 显示当前配置14.2 创建本地软件源仓库14.3 添加、启用和禁用软件源14.3.1 添加软件源14.3.2 禁用软件源14.3.3 启用软件源DNF是一款Linux软件包管理工具&#xff0c;用于管理RPM软件包。DNF可以查…...

leetcode707 设计链表 带有输入和输出的

题目&#xff1a; 设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性&#xff1a;val 和 next。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。如果要使用双向链表&#xff0c;则还需要一个属性 prev 以指示链表中的上一个节…...

100种思维模型之非sr思维模型-012

什么是sr? sr是stimulus-response的缩写&#xff0c;意思是刺激反应。 那么非sr思维模型就是非刺激反应思维模型的意思。 今天我们来聊聊非sr思维模型——一个提醒我们思考&#xff0c;提醒我们任何时刻都有选择权的思维模型。 本文依然从三个方面进行介绍&#xff0c;何谓…...

绿竹生物再冲刺港交所上市:暂未商业化,孔健夫妇为实控人

近日&#xff0c;北京绿竹生物技术股份有限公司&#xff08;下称“绿竹生物”&#xff09;在港交所递交招股书&#xff0c;准备在港交所主板上市&#xff0c;中金公司为其独家保荐人。据贝多财经了解&#xff0c;绿竹生物曾于2022年6月28日在港交所递表。 相较于此前招股书&am…...

加拿大MSB金融牌照申请方案

什么是加拿大MSB金融牌照&#xff1f; 根据犯罪所得&#xff08;洗钱&#xff09;和恐怖主义融资法案&#xff0c;您的企业必须在加拿大金融交易和报告分析中心 (FINTRAC) 注册成为货币服务企业。自 2020 年 6 月 1 日起&#xff0c;外国货币服务企业也必须在 FINTRAC 注册&…...

javaEE 初阶 — 滑动窗口

文章目录滑动窗口1 滑动窗口下如何处理丢包TCP 工作机制&#xff1a;确认应答机制 超时重传机制 连接管理机制 滑动窗口 确认应答机制、超时重传机制、连接管理机制 都是给 TCP 的可靠性提供支持的。 虽然事变的比较可靠了&#xff0c;但是是有牺牲的&#xff0c;那就是传输…...

大咖说·图书分享|狼书(卷3):Node.js高级技术

Node.js都有哪些需要掌握的高级技术&#xff1f;前端为什么同样需要学习&#xff1f; Node.js未来的发展趋势究竟如何&#xff1f;本期大咖说&#xff0c;Node布道师桑世龙携新作《狼书(卷3)&#xff1a;Node.js高级技术》展开分享。 ● 嘉宾介绍 桑世龙&#xff1a;Node布道…...

1.5配置NBMA和P2MP网络类型

1.3.3实验5:配置NBMA和P2MP网络类型 1. 实验需求 控制OSPF DR的选举修改OSPF的网络类型2. 实验拓扑 配置NBMA和P2MP网络类型实验拓扑如图1-13所示。 图1-13 配置NBMA和P2MP网络类型 3. 实验步骤 帧中继的配置如图1-14和图1-15所示...

Java面试题

三次握手&#xff0c;四次挥手中&#xff0c;为什么要挥手四次 第一次握手&#xff0c;客户端发送同步报文到服务端&#xff0c;客户端知道自己有发送数据能力&#xff0c;不知道服务端是否有发送、接受数据能力。 第二次握手&#xff0c;服务端收到同步报文&#xff0c;并回复…...

opencv锁定鼠标定位

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…...

机器连接和边缘计算

以一种高效、可扩展的方式进行连接和边缘计算的结合&#xff0c;解决了在工业物联网应用中的机器数据集成问题。 一 边缘计算 边缘计算描述了由中央平台管理的数据分散式处理。边缘计算对于工业物联网而言非常重要。在许多应用程序中&#xff0c;由于数据量非常大&#xff0c;…...

利用NGROK将本地网站发布为一个公开网站

一般与第三方服务集成时&#xff0c;需要提供https的回调URL&#xff0c;本地开发阶段可以利用NGROK将本地网站发布为公开的https网站。https://ngrok.com/downloadWindow下载地址&#xff1a;https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-windows-amd64.zip以Window…...

Vulnhub 渗透练习(一)—— Breach 1.0

环境搭建 环境下载&#xff1a; https://www.vulnhub.com/entry/breach-1,152/ 环境描述&#xff1a; Vulnhub 中对此环境的描述&#xff1a; VM 配置有静态 IP 地址 (192.168.110.140)&#xff0c;因此您需要将仅主机适配器配置到该子网。 这里我用的是 VMware &#xff0…...

初探Spring采用Spring配置文件管理Bean

文章目录Spring容器演示--采用Spring配置文件管理Bean&#xff08;一&#xff09;创建Maven项目&#xff08;二&#xff09;添加Spring依赖&#xff08;三&#xff09;创建杀龙任务类&#xff08;四&#xff09;创建勇敢骑士类&#xff08;五&#xff09;采用传统方式让勇敢骑士…...

【手写 Vuex 源码】第十二篇 - Vuex 插件机制的实现

一&#xff0c;前言 上一篇&#xff0c;主要介绍了 Vuex 插件的开发&#xff0c;主要涉及以下几个点&#xff1a; Vuex 插件的使用介绍&#xff1b;Vuex 插件开发和使用分析&#xff1b;Vuex 插件机制的分析&#xff1b; 本篇&#xff0c;继续介绍 Vuex 插件机制的实现&…...

图像去噪技术简述

随着每天拍摄的数字图像数量激增&#xff0c;对更准确、更美观的图像的需求也在增加。然而&#xff0c;现代相机拍摄的图像不可避免地会受到噪声的影响&#xff0c;从而导致视觉图像质量下降。因此&#xff0c;需要在不丢失图像特征&#xff08;边缘、角和其他尖锐结构&#xf…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解

一、前言 在HarmonyOS 5的应用开发模型中&#xff0c;featureAbility是旧版FA模型&#xff08;Feature Ability&#xff09;的用法&#xff0c;Stage模型已采用全新的应用架构&#xff0c;推荐使用组件化的上下文获取方式&#xff0c;而非依赖featureAbility。 FA大概是API7之…...