关于队列的小知识

简介: 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。

theme: smartblue

队列是常用的数据结构之一,是一种先入先出(First Input First Output)的结构。

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。

使用场景

队列一般用于生产者-消费者模式。队列有阻塞队列和非阻塞队列,两者区别为当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。这两者都能用于生产者-消费者模式,但是在选择上有细微区别。

  1. 阻塞队列
  • 供小于求的情况使用阻塞队列更加合适。如果不使用阻塞队列,则会不断轮询,耗费资源。为防止消费进程长时间等待,可以设置超时时间来解决这个问题。
  • 阻塞队列为有界队列,能够设置队列长度
  1. 非阻塞队列
  • 非阻塞队列性能更高
  • 对于实时性不那么高的场景,生产者不断生产,消费者定时消费
  • 非阻塞队列为无界队列

项目中自己写阻塞队列的情况比较少,一般消费MQ的时候会自动阻塞,超过一定时间没有消息会自动断开链接。

非阻塞队列在商品收藏功能上用过。因为商品收藏功能QPS相对高,而且会直接操作DB,导致服务不稳定。收藏业务不需要特别实时,点击收藏按钮后按钮变红,用户查看收藏列表能查看到收藏的商品,很少有人点击收藏后立即查看收藏列表。所以使用Redis的队列存储收藏请求,起定时脚本每分钟定时进行消费。

线程安全的并发队列

队列使用起来方便,但在实际生产中,需要考虑并发情况下,线程安全问题。

对于Java来说,本身提供了线程安全的并发队列:

对于Go来说,有双向链表list,可以实现队列的功能,但该结构并不是线程安全的,如果想并发使用,需要使用sync保证线程安全。

总结

重新看一下基础知识挺有意思的,总能发现很多新的知识点,也能将以前用过的知识归纳总结,还能提供一些新的写作思路。写这篇博客的时候,发现锁可是太有意思了,所以下一篇博客我打算写一下Go语言里的锁,欢迎大家到时候观看。

资料

  1. 阻塞队列与非阻塞队列区别应用场景
  2. 阻塞队列的使用场景?
  3. 简单,高效,实用的非阻塞(无锁)和阻塞并行队列算法
  4. 阻塞队列与非阻塞队列的区别
  5. [怀旧并发06]分析ReentrantLock的实现原理
  6. 什么是可重入
  7. 线程安全的并发队列
  8. CAS无锁算法与ConcurrentLinkedQueue
  9. ReentrantLock 锁详解

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

往期文章回顾:

  1. 设计模式
  2. 招聘
  3. 思考
  4. 存储
  5. 算法系列
  6. 读书笔记
  7. 小工具
  8. 架构
  9. 网络
  10. Go语言
相关文章
|
6月前
|
存储 消息中间件 前端开发
队列
队列
70 0
|
缓存
指令缓存队列
指令缓存队列
66 0
|
6月前
队列的实现
队列的实现
|
11月前
|
C++
c++ 队列
队列的数据结构
36 0
|
C语言
【Leetcode】队列实现栈和栈实现队列
【Leetcode】队列实现栈和栈实现队列
62 0
队列的实现(下)
队列的实现(下)
|
机器学习/深度学习 存储 C语言
队列的实现(上)
队列的实现(上)
|
存储
队列的使用
队列的使用
78 0