【基础篇】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_node
;tail = 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()
方法上加锁,但是锁粒度大并发度会比较低,同一时刻仅允许一个存或者取操作。
如何实现一个高效的并发队列:
- 基于数组的循环队列:避免数据搬移
- CAS原子操作:避免真正的去OS底层申请锁资源
队列的应用
基于链表的实现方式,可以实现一个支持无限排队的无界队列(unbounded queue),但是可能会导致过多的请求排队等待,请求处理的响应时间过长。所以,针对响应时间比较敏感的系统,基于链表实现的无限排队的线程池是不合适的。而基于数组实现的有界队列(bounded queue),队列的大小有限,所以线程池中排队的请求超过队列大小时,接下来的请求就会被拒绝,这种方式对响应时间敏感的系统来说,就相对更加合理。
队列可以应用在任何有限资源池中,用于排队请求,比如数据库连接池等。对于大部分资源有限的场景,当没有空闲资源时,基本上都可以通过队列这种数据结构来实现请求排队。
相关文章:
![](https://img-blog.csdnimg.cn/d6554f92db64457ab7d3d98af1463c49.png)
【基础篇】7 # 队列:队列在线程池等有限资源池中的应用
说明 【数据结构与算法之美】专栏学习笔记 什么是队列? 队列是一种操作受限的线性表数据结构,特点是先进先出,最基本的操作有:入队 enqueue(),放一个数据到队列尾部;出队 dequeue(),从队列头…...
![](https://img-blog.csdnimg.cn/c1d2de10ec7343f78235ae22a2ceee3b.png)
matlab进行双目标定获取双目参数并打印教程
文章目录前言1.打开matlab进行双目标定2.获取想要的参数前言 在相同的标定算法和标定参数下,Python和Matlab的标定精度是相同的。因为标定精度主要取决于标定算法和标定参数的质量,而不是编程语言的选择。 不同的编程语言可能使用不同的库或实现细节&…...
![](https://img-blog.csdnimg.cn/75573049aa7f4ee29b7640785b25b9b3.png)
JVM类加载机制
回到2018年的抖音哈哈. 回顾下: java开发环境: java编译运行过程: 1) 编译期:.java源文件,经过编译,生成.class字节码文件 2) 运行期:JVM加载.class并运行.class(0和1) 特点: 跨平台、一次编程,处处报错 名词解释: 1…...
![](https://www.ngui.cc/images/no-images.jpg)
8.1 优化概述
数据库性能取决于数据库级别的几个因素,例如表、查询和配置设置。这些软件结构导致了硬件级别的 CPU 和 I/O 操作,您必须将其最小化并尽可能提高效率。在研究数据库性能时,首先要学习软件端的高级规则和准则,然后使用墙上的时钟时…...
![](https://img-blog.csdnimg.cn/img_convert/1f8db2ec9c9deb91f9e97c558664aa7b.png)
从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软件包管理工具,用于管理RPM软件包。DNF可以查…...
![](https://www.ngui.cc/images/no-images.jpg)
leetcode707 设计链表 带有输入和输出的
题目: 设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节…...
![](https://img-blog.csdnimg.cn/6d36df8e48994ab6a7a8a021d8d92662.png)
100种思维模型之非sr思维模型-012
什么是sr? sr是stimulus-response的缩写,意思是刺激反应。 那么非sr思维模型就是非刺激反应思维模型的意思。 今天我们来聊聊非sr思维模型——一个提醒我们思考,提醒我们任何时刻都有选择权的思维模型。 本文依然从三个方面进行介绍,何谓…...
![](https://www.ngui.cc/images/no-images.jpg)
绿竹生物再冲刺港交所上市:暂未商业化,孔健夫妇为实控人
近日,北京绿竹生物技术股份有限公司(下称“绿竹生物”)在港交所递交招股书,准备在港交所主板上市,中金公司为其独家保荐人。据贝多财经了解,绿竹生物曾于2022年6月28日在港交所递表。 相较于此前招股书&am…...
![](https://www.ngui.cc/images/no-images.jpg)
加拿大MSB金融牌照申请方案
什么是加拿大MSB金融牌照? 根据犯罪所得(洗钱)和恐怖主义融资法案,您的企业必须在加拿大金融交易和报告分析中心 (FINTRAC) 注册成为货币服务企业。自 2020 年 6 月 1 日起,外国货币服务企业也必须在 FINTRAC 注册&…...
![](https://img-blog.csdnimg.cn/60741a39e579478282c2c882f373c34b.png#pic_center)
javaEE 初阶 — 滑动窗口
文章目录滑动窗口1 滑动窗口下如何处理丢包TCP 工作机制:确认应答机制 超时重传机制 连接管理机制 滑动窗口 确认应答机制、超时重传机制、连接管理机制 都是给 TCP 的可靠性提供支持的。 虽然事变的比较可靠了,但是是有牺牲的,那就是传输…...
![](https://img-blog.csdnimg.cn/66e7d8f200a34e1a974a6301ec96e698.jpeg)
大咖说·图书分享|狼书(卷3):Node.js高级技术
Node.js都有哪些需要掌握的高级技术?前端为什么同样需要学习? Node.js未来的发展趋势究竟如何?本期大咖说,Node布道师桑世龙携新作《狼书(卷3):Node.js高级技术》展开分享。 ● 嘉宾介绍 桑世龙:Node布道…...
![](https://img-blog.csdnimg.cn/a9f72bb1d896439ca6a1679011bf007a.png)
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所示...
![](https://www.ngui.cc/images/no-images.jpg)
Java面试题
三次握手,四次挥手中,为什么要挥手四次 第一次握手,客户端发送同步报文到服务端,客户端知道自己有发送数据能力,不知道服务端是否有发送、接受数据能力。 第二次握手,服务端收到同步报文,并回复…...
![](https://img-blog.csdnimg.cn/b4c687972d3649f4a134ca76da0fce52.gif)
opencv锁定鼠标定位
大家好,我是csdn的博主:lqj_本人 这是我的个人博客主页: lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…...
![](https://img-blog.csdnimg.cn/61c827c102f04a07a43a43647e2f9d3a.gif)
机器连接和边缘计算
以一种高效、可扩展的方式进行连接和边缘计算的结合,解决了在工业物联网应用中的机器数据集成问题。 一 边缘计算 边缘计算描述了由中央平台管理的数据分散式处理。边缘计算对于工业物联网而言非常重要。在许多应用程序中,由于数据量非常大,…...
![](https://img-blog.csdnimg.cn/img_convert/824ee67ad4554c038cb643da348e3cba.png)
利用NGROK将本地网站发布为一个公开网站
一般与第三方服务集成时,需要提供https的回调URL,本地开发阶段可以利用NGROK将本地网站发布为公开的https网站。https://ngrok.com/downloadWindow下载地址:https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-windows-amd64.zip以Window…...
![](https://img-blog.csdnimg.cn/37052c4e3f5940078c81e6f432ac4177.png)
Vulnhub 渗透练习(一)—— Breach 1.0
环境搭建 环境下载: https://www.vulnhub.com/entry/breach-1,152/ 环境描述: Vulnhub 中对此环境的描述: VM 配置有静态 IP 地址 (192.168.110.140),因此您需要将仅主机适配器配置到该子网。 这里我用的是 VMware ࿰…...
![](https://img-blog.csdnimg.cn/78e80df82b8e413c9b0d4cf267142d7b.png)
初探Spring采用Spring配置文件管理Bean
文章目录Spring容器演示--采用Spring配置文件管理Bean(一)创建Maven项目(二)添加Spring依赖(三)创建杀龙任务类(四)创建勇敢骑士类(五)采用传统方式让勇敢骑士…...
![](https://img-blog.csdnimg.cn/img_convert/95ddd1e91c587346a80faff0f18ff130.png)
【手写 Vuex 源码】第十二篇 - Vuex 插件机制的实现
一,前言 上一篇,主要介绍了 Vuex 插件的开发,主要涉及以下几个点: Vuex 插件的使用介绍;Vuex 插件开发和使用分析;Vuex 插件机制的分析; 本篇,继续介绍 Vuex 插件机制的实现&…...
![](https://img-blog.csdnimg.cn/150b0c1638ea4c2e85fd7174ad85dc04.png)
图像去噪技术简述
随着每天拍摄的数字图像数量激增,对更准确、更美观的图像的需求也在增加。然而,现代相机拍摄的图像不可避免地会受到噪声的影响,从而导致视觉图像质量下降。因此,需要在不丢失图像特征(边缘、角和其他尖锐结构…...
![](https://img-blog.csdnimg.cn/4492988e5bf04d5a912809c9f0ec345b.jpeg)
数据迁移——技术选型
日常我们在开发中,随着业务需求的变更,重构系统是很常见的事情。重构系统常见的一个场景是变更底层数据模型与存储结构。这种情况下就要对数据进行迁移,从而使业务能正常支行。 背景如下:老系统中使用了mongo数据库,由…...
![](https://www.ngui.cc/images/no-images.jpg)
第二十七章 java并发常见知识内容(CompletableFuture)
JAVA重要知识点CompletableFuture常见函数式编程操作创建 CompletableFuture静态工厂方法处理异步结算的结果异常处理组合 CompletableFuturethenCompose() 和 thenCombine() 区别并行运行多个 CompletableFutureCompletableFuture Java 8 才被引入的一个非常有用的用于异步编…...
![](https://www.ngui.cc/images/no-images.jpg)
Qt扫盲-QMake 使用概述
QMake 使用概述一、概述二、简单开始三、使应用程序可调试1. 添加平台特定的源文件2. 如果文件不存在,停止qmake3. 检查多个条件一、概述 本教程教你qmake的基础知识。qmake 其实就是一个自动化编译的流程控制文件,也是Qt程序的生成makefile的工具&…...
![](https://img-blog.csdnimg.cn/64ccfba157e1495c9677016cb77374c6.png)
Spring Cloud之Zuul
目录 简介 Zuul中的过滤器 过滤器的执行流程 使用过滤器 route过滤器的默认三种配置 路由到服务 路由到url地址 转发给自己 自定义过滤器 简介 Zuul是Netflix开源的微服务网关,主要功能是路由转发和过滤器,其原理也是一系列filters࿰…...
![](https://img-blog.csdnimg.cn/img_convert/a233ee77903c3664d2556486ab281817.png)
为什么要有分布式锁?
Redis避坑指南:为什么要有分布式锁?作者:京东保险 张江涛1、为什么要有分布式锁?JUC提供的锁机制,可以保证在同一个JVM进程中同一时刻只有一个线程执行操作逻辑;多服务多节点的情况下,就意味着有…...
![](https://img-blog.csdnimg.cn/90b4fe544e67473c9163ed8fe25747cb.png)
【Redis】Redis持久化之RDB详解(Redis专栏启动)
📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建工设优化。文章内容兼具广度深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公…...
![](https://img-blog.csdnimg.cn/6ed83842c0e1487aa9afdf40c000eb0c.png)
Retinanet网络与focal loss损失
参考代码:https://github.com/yhenon/pytorch-retinanet 1.损失函数 1)原理 本文一个核心的贡献点就是 focal loss。总损失依然分为两部分,一部分是分类损失,一部分是回归损失。 在讲分类损失之前,我们来回顾一下二…...
![](https://www.ngui.cc/images/no-images.jpg)
Spring事务的失效场景
事务失效场景 方法用private或final修饰 Spring底层使用了AOP,而AOP的实现方式有两种,分别是JDK动态代理和CGLIB,JDK动态代理是实现抽象接口,CGLIB是继承父类,无论哪种方式,都需要重写方法来进行方法增强,而…...
![](https://www.ngui.cc/images/no-images.jpg)
芯动联科在科创板IPO过会:拟募资10亿元,金晓冬为实际控制人
2月13日,上海证券交易所披露的信息显示,安徽芯动联科微系统股份有限公司(下称“芯动联科”)获得科创板上市委会议审议通过。据贝多财经了解,芯动联科于2022年6月24日在科创板递交招股书。 本次冲刺上市,芯…...
![](https://img-blog.csdnimg.cn/c56dead6e6944057bedd7f08c1ab2130.png)
数据结构之单链表
一、链表的组成 链表是由一个一个的节点组成的,节点又是一个一个的对象, 相邻的节点之间产生联系,形成一条链表。 例子:假如现在有两个人,A和B,A保存了B的联系方式,这俩人之间就有了联系。 A和…...
![](/images/no-images.jpg)
做网站的人是什么职位/全球疫情最新数据
案例一 导入图片思路: 1.导入库 2.加载图片 3.创建窗口 4.显示图片 5.暂停窗口 6.关闭窗口# 1.导入库import cv2# 2.加载图片img cv2.imread(a.png)# 3.创建窗口cv2.namedWindow(window 1 haha)# 4.显示图片cv2.imshow(window 1,img)# 5.暂停窗口cv2.waitKey(0)# 6.关闭窗口cv…...
![](https://img-blog.csdnimg.cn/20200629182251721.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0NTRE4yNDk3MjQyMDQx,size_16,color_FFFFFF,t_70)
沈阳 网站建设/网站网页设计
前言:打脸了,前脚刚说过要跟Servlet正式告别。结果最近的面试被问到了同一个Servlet可不可以被映射到多个URL上,也就是如何用一个Servlet实现多个功能。 前置知识: Servlet容器如何处理请求资源路径? 1、这个地址 ht…...
![](https://img-blog.csdnimg.cn/92166a17a189438f8110aa848adf98fd.gif#pic_center)
河北网站开发多少钱/如何免费推广一个网站
文章目录流程循环数组简单案例先看看效果图 流程 使用数组的slice() 方法通过条件判断截取原数组相应内容组成新数组 循环数组 let currentPage 0 // arr:原数组 newLen:新数组需要的长度 currentPage:现在的页码// 方法一: function loopData(arr, newLen) {…...
![](https://yqfile.alicdn.com/fab1a2b29fed9792f06ff13dcd26b21d2de9b3c9.png)
新版wordpress增加备案/一键识图找原图
锤子“坚果手机”发布会因故推迟、PPT一堆错漏、抢红包故障,据悉是因锤子官网服务 器遭遇了数十G流量DDoS恶意攻击,现场PPT也是临时赶制、边写边用。关于DDoS攻击(分布式拒绝服务),Akamai技术公司也发布了二季度的互 联…...
我想学制作网站吗/网站排名seo教程
软件版本 ArcGISServer 10.6 做了双网卡绑定之后,启动arcgisserver,通过top命令查看 Java进程在出现五秒钟之后消失 查看错误日志 出现 Exception in thread “main” com.esri.arcgis.discovery.nodeagent.NodeAgentException: Could not start RMI co…...
![](/images/no-images.jpg)
企业网站管理系统程序名称/竞价排名规则
简单的并行加速计算(python) backend:用于设置并行方式, 多进程方式有’loky’(更稳定)和’multiprocessing’两种可选项, 多线程方式有’threading’一种选项。默认为’loky’ n_jobs&#x…...