作者 |  小鹿

来源 |  小鹿动画学编程

写在前边

像线程池、异步队列、消息队列等有限的资源容器中,往往存储大量的任务事件,这些大量的任务事件需要进行有条理的进行任务分发以及各种情况处理,为了能够使得资源容器的正常运行,不得不使用一定的容器结构设计和策略,那么这些结构和策略如何实现的呢?

那小鹿不买官司了,就是用我们今天即将学到的数据结构“队列”。虽然我们初学者实际中接触的少,但是它的实际用途广着呢,学好这部分是非常关键的。

思维导图

1

什么是队列?

何为队列?顾名思义,排队就是一个很好的例子。如果我们餐厅刷卡买饭,学生依次排队,已购买完饭的在队头走了,刚来的同学就要排在队尾后边排队。而不能直接在排好队中插队,这样也坏了排队这种“先来先去”规矩。

2

队列的特点?

栈有出栈和入栈两种,队列也有入队和出队两种操作,只不过是栈是先来后走,队列则相反,先来先走。

正是因为队列这种特点,使得它在一些有限的资源容器中的到广泛的应用,比如线程池、资源池、消息队列等。

3

如何实现队列?

队列和栈一样,也有两种实现方式,一种是顺序队列,一种是链式队列。但是我们之前的文章中说过,无论是顺序还是链式,都是由数组和链表演化而来,只不过是操作上进行了改进。

1、顺序队列

对于上边的数组顺序队列,不知道大家有没有发现一个问题就是,如果我一直的出队、入队会出现下边这样一种情况。

此时队列再入队,但是队尾已满,但是我们看到的明明队头还有空间的,如果此时扩大容量不就相当于浪费空间吗?

那还有一个方法就是,每入队一个元素,整体数据就往前移动一个空间,你可能会说,这样操作起来是不是很费劲,而且效率不高,是的,这样的确效率不高。

如果我们稍微改进一下,如果队尾有空间,我们就让元素一直入队,直到队尾没有空间位置,然后进行整体进行一次搬移,这样优化了入队的效率。将这一次性进行大量搬移数据平均到每次上,平均时间复杂度还是 O(1)。

2、链式队列

链式队列是以链表组成的,它的优点就是可以无限的进行入队,不用动态扩容。

4

队列的种类?

4.1 循环队列

循环队列,顾名思义,将一般的队列进行头尾相接,形成一个圆,声明两个指针,一个带边队头,一个代表队尾,入队和出队的时候,直接操作对应的指针即可。

但是为什么会出现循环队列呢?是否还记得我们上边所述,普通的队列需要进行大量数据搬移,而循环队列则没有这个缺点。

但是循环队列有一个比较重要的点就是判空和判断是否已满。

如上图所示,判空的条件很简单,头指针等于尾指针的时候,此时循环队列为空。

循环队列满的时候,我们要发现其上边的规律得出队满的条件,(尾指针 + 1)% n = 头指针。此时的循环队列会浪费一个空间。

上边我们涉及到的队列是从结构上进行来区分的,下面我们就从实际开发功能上进行划分。其实就是对一些功能的需求对队列操作上设定了一定的要求。

4.2 阻塞队列

我们拿一个例子入手,如果你学习过Android开发,里边有个MessageQueue消息队列。如果没有接触过,也没关系,可以将其理解为放置消息的一个容器。

这个容器主要存放系统给它分发的任务消息,然后当有线程来分配任务的时候,此时该容器,也就是消息队列就会在队列中拿出任务然后分发给线程去执行。但是有这样两种情况需要进行设计。

第一种情况就是当任务消息队列没有任务的时候,此时线程来拿任务,该怎么办?

第二种情况就是,当没有空闲线程来取任务,此时任务消息队列已经满了,系统再分发新的任务时,又该如何处理呢?

那我相对于这两种情况,就用到我们的阻塞队列。当遇到第一种情况时,此时消息队列为空,在队头拿数据的时候会被阻塞,也就是被阻止了,因为队列中为空,只有等到队列中有新的数据时,线程才可以拿去新的任务。

当遇到第二种情况,如果队列已经满了,此时没有空余线程来取任务,此时队列也被阻塞了,当有空余线程来获取任务的时候,任务队列才可取数据。

其实上边的设计思路和我们所涉及到的设计模式中的 “发布-订阅者模式”相同。

生产者代表往消息队列中增加数据,消费者代表线程不断的拿去任务去执行,我们可以通过调节生产着和消费者的数量来调节队列汇总的任务数量,从而达到高效的系统运行。

4.3 并发队列

上边我们涉及到的阻塞队列会有很多的消费者(线程)去操作队列。我们举个具体点的例子,还是拿排队打饭的例子,如果一个窗口没有排序秩序,100 多个人都往窗口买饭,如果你作为卖饭的,想象一下会出现什么情况呢?

学生争来争去到底先给哪一个盛饭呢?一旦人一多,可能整个餐厅窗口挤爆,会出现打架的情况。

话说回来,在系统中也可能出现这种情况的,那我们怎么对付这种情况呢?此时的队列不再叫做阻塞队列,叫做并发队列。

我们只需要设置一个锁机制,当有一个消费者来取任务的时候,我们此时加一个锁,说明其他的消费者不能进行操作了,当这个消费者读取完任务时,在解锁,依次类推,这样保证了系统的正常运行。

总结

最后我们来总结一下队列的应用,像我们开篇所说,队列一般应用在有限的资源场景中,比如消息队列、异步队列、CPU 的线程执行队列等。对于这些应用场景,都是利用了队列先来先去的服务调度方式,从而能够准确的对资源进行把控。

队列在实际应用中也分为两种,一种是基于数组的顺序队列,另一种是基于链表的链式队列。它们两者各有优缺点,所谓的优缺点也是由数组和两边本身的优缺点演化而来。

数组大小固定,如果有过多的请求,就会导致长时间排队等候,请求响应时间过长。而链式队列虽然可以动态的添加任务,但是如果过于太长,在实际应用中也是不允许的。

对于如何在实际应用中设计一个合适的队列,需要根于已有的资源容量以及需求,还有系统的响应时间要求进行设计。如果队列太长,会导致等待请求过多,队列太小,就无法充分利用系统的资源。

基础知识

基础数据结构:【动画】如何轻松手写链表?

三分钟基础知识:什么是栈?

三分钟基础知识:互斥那点事儿(上)

三分钟基础知识:互斥那点事儿(下)

三分钟基础知识:用动画给面试官解释 TCP 三次握手过程

三分钟基础知识:用动画给女朋友讲解 TCP 四次分手过程

队列判空_三分钟基础:什么是队列?相关推荐

  1. 队列判空_数据结构与算法——队列的C语言实现

    本人原创,有问题请评论,楼主会随时回来查看修改滴~ 觉得有用请点个赞哦~~ 1.顺序队 /** 2020.04:queue 顺序结构-循环队列 判空 判满 求长度 入队 出队 获取队头 获取队尾 */ ...

  2. 串口发送tcp数据 源端口号_三分钟基础知识:用动画给面试官解释 TCP 三次握手过程...

    作者 |  小鹿 来源 |  小鹿动画学编程 写在前边 TCP 三次握手过程对于面试是必考的一个,所以不但要掌握 TCP 整个握手的过程,其中有些小细节也更受到面试官的青睐. 对于这部分掌握以及 TC ...

  3. mysql和oracle冲突吗_三分钟带你分清MySQL 和Oracle之间的误区

    原标题:三分钟带你分清MySQL 和Oracle之间的误区 来自:华为云开发者社区 摘要:MySQL和Oracle,别再傻傻分不清. MySQL 和Oracle 在开发中的使用是随处可见的,那就简单去 ...

  4. spring字符串判空_字符串工具类StringUtils实现字符串是否中文、字符串分割/判空/替换/查找、是否包含乱码及字符串数组合并等常规操作...

    一.前言 关于字符串工具类StringUtils实现字符串是否包含isChinese中文.是否包含isMessyCode乱码.常规数据类型转换.替换/删除/判空.两字符串数组mergeStringAr ...

  5. 云技术是什么_三分钟了解云技术的原理与发展

    什么是云技术 定义 云技术(Cloud technology)基于云计算商业模式应用的网络技术.信息技术.整合技术.管理平台技术.应用技术等的总称,可以组成资源池,按需所用,灵活便利.云计算技术将变成 ...

  6. outlook qr码在哪里_三分钟前:丽江洋葱店主邀请码在哪里看呢

    三分钟前:丽江洋葱店主邀请码在哪里看呢 Y0a0e1j1m 三分钟前:丽江洋葱店主邀请码在哪里看呢 黄的早晨,学员出门吃早餐,先生.主管,旁边摆着的小型馆,一张宣传海报提醒路人出门,万一来不及开口,会 ...

  7. Juniper 210 密码清不掉_三分钟学会如何找回mysql密码

    一.在测试工作中我们肯定会写一些sq查询语句方便我们验证数据是否正确,从而判断当前软件是否存在缺陷,但是查询的过程中肯定需要我们先连接数据库,如果数据库密码忘记我们就无法完成工作,这里就教会大家如何快 ...

  8. mongodb 输出数组字段_三分钟 mongodb 开发快速上手

    三分钟 mongodb 开发快速上手 小熊昨天晚上做了一个非常真实的噩梦,有读者朋友催我"怎么又没有发文!让我们等的好辛苦",今天一睁开眼眼看后台留言,特么,居然是真的! 我bil ...

  9. 常用的数据结构_三分钟了解区块链常用数据结构「默克尔树」

    免责声明:本文旨在传递更多市场信息,不构成任何投资建议.文章仅代表作者观点,不代表火星财经官方立场. 小编:记得关注哦 来源:万向区块链 原文标题:三分钟了解区块链常用数据结构「默克尔树」 默克尔树是 ...

最新文章

  1. php 获取key的位置,PHP使用腾讯地图获取指定地址坐标:创建key(图文+视频)
  2. python 并行计算 并行方法总结 concurrent.futures pp pathos multiprocessing multiprocess模块 总结对比
  3. python是什么公司开发的软件-python适合开发桌面软件吗?
  4. linux shell之把文本里面的;替换成\n格式输出
  5. django 与 vue 的完美结合
  6. python基础编程题、积分面积_Python基础编程题100列目录
  7. c语言中 flag.bit7,利用proteus学习ARM(LPC2103)之二:熟悉IAR C语言开发环境
  8. 力胜机器人_德男子两手臂尺寸悬殊 超粗右臂曾力胜掰手腕机器人
  9. cadence从原理图导出器件库_一种cadence中原理图替换元器件库的方法与流程
  10. Filesystem Hierachy Standard 文件系统层级标准详解
  11. 阿里云国际版账号登录不上去,账号被风控怎么办?
  12. 为地图marker 设置网络图片
  13. QT—常用容器 QStringList,QVector,QMap,QHash,QVariant
  14. java实现心型代码
  15. 2022年熔化焊接与热切割试题及答案
  16. 顺序表前m和后n元素交换位置
  17. MPLS V*N OptionC1 RR
  18. go配置sublime text时使用MarGo报错及解决方法
  19. 如何使用Python进行异常检测?我来教你呀~
  20. vbs版的语音报时程序

热门文章

  1. C++ explicit的作用
  2. nginx的模块开发
  3. Java并发编程举例Runnable, Callable, Future, FutureTask, CompletionService
  4. idea下org.apache.commons.dbcp.BasicDataSourc找不到
  5. 数据库不推荐使用外键的9个理由
  6. leetcode 1143. Longest Common Subsequence | 1143. 最长公共子序列(动态规划,暴力递归->傻缓存->dp)
  7. 面试必会系列 - 1.5 Java 锁机制
  8. 如何使用markdown编辑器?官方文档在此
  9. Spring boot 自定义banner
  10. zookeeper客户端库curator分析