首页 > 其他分享 >队列

队列

时间:2024-04-18 16:55:44浏览次数:16  
标签:队列 阻塞 DelayQueue 线程 take put

队列

目录

LinkedBlockingQueue 阻塞队列

  • 新增操作
    • add队列满的时候抛出异常
    • offer队列满的时候返回false
  • 查看并删除
    • remove 队列空的时候抛出异常
    • poll 队列空的时候返回null
  • 只查看不删除操作
    • element队列空的时候抛异常
    • peek 队列空的时候返回null
  • 类描述
    • 基于链表的阻塞队列,其底层的数据结构是链表
    • 链表维护先入先出队列,新元素被放在队尾,获取元素从队头拿。
    • 链表大小在初始化的时候可以设置,默认是Integer的最大值
    • 可以使用Collection和Iterator两个接口的所有操作,因为实现了两者的接口
  • 内部构成
    • 链表存储 + 锁 + 迭代器
    • 链表的作用是保存当前节点,节点中的数据可以是任意 东西是一个泛型,比如说队列被应用到线程池时,节点就是线程。比如队列被应用到消息队列上,节点就是消息,节点的含义主要看队列被使用的场景
    • 锁有take锁和put锁 是为了保证队列操作时的线程安全,设计两种锁,是为了take和put两种操作可以同时进行 互不影响

SynchronousQueue 交换队列

  • 类描述
    • 队列不存储数据,所以没有大小 无法迭代
    • 插入操作的返回必须等待另一个线程完成对应数据的删除操作,反之亦然。
    • 队列由两种数据结构祖册,分别是后入先出的堆栈和先入先出的队列。堆栈是非公平的,队列是公平的。
    • 默认无参构造器是非公平的
  • 栈实现
    • 其阻塞的策略,并不是一上来就阻塞住,而是在自旋一定次数后,仍然没有其它线程来满足自己的要求时,才会真正的阻塞住。
  • 队列实现
    • 次 put 数据的时候,都 put 到队尾上,而每次拿数据时,并不是直接从队头拿数据,而是从队尾往前寻找第一个被阻塞的线程,这样就会按照顺序释放被阻塞的线程

DelayQueue 延时队列

  • 类描述
    • 队列中元素将在过期时被执行,越靠近队头,越早过期。
    • 未过期的元素不能够被take
    • 不允许空元素
  • 实现要求
    • delayQueue中的元素必须是Delayed的子类;Delayed是表达延迟能力的关键接口 其继承了Comparable接口 并定义了还剩多久过期的方法
    • 内部排序用的是ProorityQueue队列 超时阻塞使用的事锁的等待能力

ArrayBlockingQueue 有界循环队列

  • 类描述
    • 有界的阻塞数组,容器一旦被创建,后续大小无法被修改
    • 元素士有序的,按照先入先出进行排序,从队尾插入数据,从队头拿数据
    • 队列满时,往队列中put 数据会被阻塞,从队列中拿数据也会被阻塞
  • 数据结构
    • takeIndex
    • putIndex
    • removeIndex
    • private final ReentrankLock lock (可重入锁)
    • private final Condition notEmpty (take的队列)
    • private final Condition notFull (put的队列)

常见面试题

  • 队列 如何实现阻塞的?
    • 队列本身并没有实现阻塞的功能,而是利用 Condition 的等待唤醒机制,阻塞底层实现就是更改线程的状态为沉睡。
  • 工作中经常使用队列put take方法有什么危害 如何避免?
    • 两个方法都是无限阻塞 没有超时的意思,容易使得线程全部阻塞住,大流量时,导致机器无线程可用,所以在大流量的时候使用offer 和poll 方法来代替两者,只要设置好超时时间,在规定时间内未获取到值就会返回默认值,这样不会导致流量大时,所有线程都阻塞住了。
  • 数据入队之后有没有办法让队列过一会在执行?
    • 可以的,DelayQueue 提供了这种机制,可以设置一段时间之后再执行。
    • 缺点:无法持久化,容易数据丢失,一般使用中间件的中间件会进行持久化
  • DelayQueue对元素有要求么,把String可以放到队列中么?
    • DelayQueue要求必须实现Delayed接口,Delayed 本身又实现了 Comparable 接口 , Delayed 接 口 的 作 用 是 定 义 还 剩 下 多 久 就 会 超 时 , 给 使 用 者 定 制 超 时 时 间 的 ,Comparable 接口主要用于对元素之间的超时时间进行排序的,两者结合,就可以让越快过期的元素能够排在前面。所以把 String 放到 DelayQueue 中是不行的,编译都无法通过,DelayQueue 类在定义的时候,是有泛型定义的,泛型类型必须是 Delayed 接口的子类才行。
  • 如何看SynchronousQueue队列的大小?
    • 无容量队列,其内部size方法返回的是0
  • synchronousQueue 底层有两种数据结构,分别是队列和栈
    • 队列维护了先入先出
    • 栈先入后出
  • 假设 SynchronousQueue 底层使用的是堆栈,线程 1 执行 take 操作阻塞住了,然后有线程 2 执行 put 操作,问此时线程 2 是如何把 put 的数据传递给take 的?
  • 首先线程 1 被阻塞住,此时堆栈头就是线程 1 了,此时线程 2 执行 put 操作,会把 put 的数据赋值给堆栈头的 match 属性,并唤醒线程 1,线程 1 被唤醒后,拿到堆栈头中的 match 属性,就能够拿到 put 的数据了

标签:队列,阻塞,DelayQueue,线程,take,put
From: https://www.cnblogs.com/heyanfeng/p/18142893

相关文章

  • 阿里云消息队列升级全新品牌 ApsaraMQ丨阿里云云原生 3 月产品月报
    云原生月度动态云原生是企业数字创新的最短路径。《阿里云云原生每月动态》,从趋势热点、产品新功能、服务客户、开源与开发者动态等方面,为企业提供数字化的路径与指南。趋势热点......
  • 队列-优先级队列
    队列-优先级队列1.定义:优先级队列是一种特殊的队列,其中每个元素都有一定的优先级。元素的出队顺序是根据它们的优先级决定的,而不是它们被加入队列的顺序。高优先级的元素会先于低优先级的元素出队。2.实现方式:优先级队列通常通过堆(特别是二叉堆)来实现,以保证高效的元素插入和......
  • 数据结构-队列
    数据结构-队列1.定义:队列是一种遵循先进先出(FIFO,FirstInFirstOut)原则的线性数据结构。在队列中,元素从一端添加(队尾),从另一端移除(队头)。classQueue:def__init__(self):self.items=[]主要操作:队列的主要操作包括enqueue(向队尾添加元素)、dequeue(从队头......
  • JDK11下的优先级队列小问题
    优先级队列中存了我自定义的对象,比较规则写好了,存完了之后我去修改堆中对象的值(比较器中写的值),发现堆没有即刻相应调整,导致结果不对但是每次我让堆中出一个,再进一个堆就调整好了暂时不知道什么原因,猜测可能是堆中存对象的话需要改动才会调整。......
  • 【1】消息队列概念
    一、什么是消息队列消息队列中间件,又称为消息队列或者消息中间件,是在消息的传输过程中保存消息的容器。二、消息队列模型JMS规范目前支持两种消息模型:点对点(pointtopoint,queue)和发布/订阅(publish/subscribe,topic)。消息不可重复消费。2.1、点对点模型点对点模式是基于队列......
  • Kafka做消息队列的原理
    Kafka作为消息队列的实现原理主要基于其分布式架构和日志式存储机制。以下是Kafka作为消息队列工作的核心原理:1.分布式架构与分区:Kafka采用分布式架构,将数据分布存储在多个节点(称为Broker)上,以实现数据的水平扩展和并行处理。Kafka中的消息流被组织成主题(Topic),每个主题可以包......
  • 队列 - 双端队列实现
    之前实现的单端队列,只能从队列的尾部进,头部出.但现在我们来实现一种从两端都可进行出队入队的结构,即双端队列deque.在计算机中,双端队列最常用的一个场景是存储一系列的撤销操作.当然用户点击了某个操作,则此操作会被存在一个双端队列中,类似栈里.当用户点击撤销操......
  • 说说你对栈、队列的理解?应用场景?
    一、栈栈(stack)又名堆栈,它是一种运算受限的线性表,限定仅在表尾进行插入和删除操作的线性表表尾这一端被称为栈顶,相反地另一端被称为栈底,向栈顶插入元素被称为进栈、入栈、压栈,从栈顶删除元素又称作出栈所以其按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶......
  • 队列的基本操作
    (一)结构体定义一个顺序队列typedefstruct{chardata[maxsize];intrear,front; }sqQueue;(二)队列的初始化头尾两个指针指向0voidInitQueue(sqQueue*s){ (*s).rear=(*s).front=0;}(三)进队操作 注意循环队列的使用intEnQueue(sqQueue*Q,charx)//入队{ ......
  • 数据结构之队列(java语言版)
    队列(Queue):在逻辑上是一种线性存储结构。它有以下几个特点:1、队列中数据是按照"先进先出(FIFO,First-In-First-Out)"方式进出队列的。2、队列只允许在"队首"进行删除操作,而在"队尾"进行插入操作。队列通常包括的两种操作:入队列和出队列。队列的种类也很多,单向队列,双向队列,循......