【Java数据结构及算法实战】系列007:Java队列01——Queue概述

简介: 列与栈类似,也是一种运算受限的线性表。队列则被限定在表尾进行插入、在表头进行删除,这种数据结构,实现了FIFO(First In First Out,先进先出)或者是LILO(Last In Last Out,后进后出)的方式工作。

队列与栈类似,也是一种运算受限的线性表。队列则被限定在表尾进行插入、在表头进行删除,这种数据结构,实现了FIFO(First In First Out,先进先出)或者是LILO(Last In Last Out,后进后出)的方式工作。

 

 

 

下图很形象将队列比作是实现生活中的排队。排在队列前面的总是会最先得到处理,而排在队列后面的总是最后得到处理。

 

 

 

 

 

 

1.   队列的基本概念

 

 

 

 

 

在对队列有了基本的认识之后,我们再来看下队列的基本概念。

 

 

 

进行插入操作这一端被称为队尾(tail),相对地,把另一端称为队首(head)。向一个队列插入新元素又称作入队(enqueue)。它是把新元素放到队尾元素的之后,使之成为新的队尾元素。从一个队列中删除元素又称作出队(dequeue)。它是把队首元素删除掉,使其相邻的元素成为新的队首元素。

 

 

 

 

 

 

 

2.   Java对于队列的支持

 

 

 

在Java中,提供了java.util.Queue<E>接口以支持队列。根据实现不同,队列又可以分为以下几种场景。

 

 

 

 

 

2.1.     是否阻塞

 

阻塞是指当队列空时,消费资源是否阻塞;当队列(有界队列)满时,插入数据是否阻塞。

 

 

 

Java提供了java.util.concurrent.BlockingQueue<E>接口以表示阻塞队列。常见的阻塞队列有:

 

 

 

l  ArrayBlockingQueue

 

l  LinkedBlockingQueue

 

l  DelayQueue

 

l  PriorityBlockingQueue

 

l  SynchronousQueue

 

l  LinkedBlockingDeque

 

l  等等

 

2.2.     单端还是双端

 

单端还是双端,相比于单端队列,双端队列可以从队列的两头分别进行入队和出队操作。

 

 

 

Java提供了java.util.Deque<E>接口以表示双端队列。常见的双端队列有:

 

 

 

l  ArrayDeque

 

l  ConcurrentLinkedDeque

 

l  LinkedList

 

l  LinkedBlockingDeque

 

l  等等

 

 

 

2.3.     是否有界

 

 

 

判断一个队列是否有界的依据是,队列在初始化时是否设置了容量。以ArrayBlockingQueue为例,ArrayBlockingQueue在初始化时,强制要求以容量作为构造函数的参数之一,这便是有界的。LinkedList是无界的,队列的长度会随着入队的元素的增多而不断增长。

 

 

 

LinkedBlockingQueue比较特殊,在初始化时可以指定容量也可以不指定容量。当初始化LinkedBlockingQueue指定容量时,是有界队列;当初始化LinkedBlockingQueue未指定容量时,其内部会以Integer.MAX_VALUE值作为容量。当然,因为Integer.MAX_VALUE值非常大,近似无限大,因此LinkedBlockingQueue未指定容量时也可以近似认为是无界队列。

 

 

 

在实际项目中,推荐优先选择使用有界队列。因为无界队列可能产生OOM(Out Of Memory,内存溢出)问题,OOM对系统是致命的。

 

 

 

2.4.     内部数据结构

 

队列的内部数据结构对使用者而言应该是透明的,使用者关注内部数据结构。主要是关注数据结构对业务运行的影响。队列的内部数据结构有数组、链表、堆等,不同数据结构会影响GC、CPU缓存,大长时间运行后,使用链表会产生大量的碎片,对GC造成很大的压力;内存连续的空间,也更有利于CPU缓存的发挥。

 

 

 

根据存储结构的不同,队列还分为以下几种:

 

 

 

l  用顺序表实现的队列称为顺序队列

 

l  用链表实现的队列称为链队列

 

 

 

2.5.     是否无锁

 

加锁的开锁是巨大的,在高并发场景下,无锁的性能一般有锁的数倍。

 

2.6.     其他特殊功能

 

有很多队列都有特殊的功能,来满足特殊的场景。如SynchronousQueue没有缓存用于handoff场景(下文介绍);PriorityQueue、PriorityBlockingQueue支持按优先级入队;DelayedQueue支持延时出队;Disruptor除具有超强的性能外,还支持多消费者复杂的消费模式。

 

 

 

 

 

基于上面的场景,整理了下表最常用的10个队列的实现。

 

 

 

表1-1 最常用的10个队列的实现

                                                                                                                                                                                                                                                                                               

   

队列

   
   

是否阻塞

   
   

单端还是双端

   
   

是否有界

   
   

内部数据结构

   
   

是否无锁

   
   

特殊功能

   
 

ArrayBlockingQueue

 
 

阻塞

 
 

单端

 
 

 
 

数组

 
 

有锁

 
 

NA

 
 

LinkedBlockingQueue

 
 

阻塞

 
 

单端

 
 

 
 

链表

 
 

有锁

 
 

NA

 
 

SynchronousQueue

 
 

阻塞

 
 

单端

 
 

 
 

单一元素

 
 

有锁

 
 

支持HandOff功能;

 
 

LinkedTransferQueue

 
 

阻塞

 
 

单端

 
 

 
 

链表

 
 

有锁

 
 

功能为LinkedBlockingQueue与SynchronousQueue的超集;

 
 

PriorityBlockingQueue

 
 

阻塞

 
 

单端

 
 

 
 

 
 

有锁

 
 

支持优先级队列;

 
 

DelayQueue

 
 

阻塞

 
 

单端

 
 

 
 

 
 

有锁

 
 

支持延时出队;

 
 

LinkedBlockingDeuqe

 
 

阻塞

 
 

双端

 
 

 
 

链表

 
 

有锁

 
 

NA

 
 

ConcurrentLinkedQueue

 
 

非阻塞

 
 

单端

 
 

 
 

链表

 
 

有锁

 
 

NA

 
 

ConcurrentLinkedDeque

 
 

非阻塞

 
 

双端

 
 

 
 

链表

 
 

有锁

 
 

NA

 
 

Disruptor

 
 

阻塞

 
 

单端

 
 

 
 

环形数组

 
 

无锁

 
 

超强性能,支持多种生产者消费者模式;

 

 

参考引用

 

目录
相关文章
|
8月前
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
278 1
|
5月前
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
176 1
|
5月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
168 0
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
9月前
|
算法 Java
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
265 3
 算法系列之数据结构-Huffman树
|
9月前
|
算法 Java
算法系列之数据结构-二叉搜索树
二叉查找树(Binary Search Tree,简称BST)是一种常用的数据结构,它能够高效地进行查找、插入和删除操作。二叉查找树的特点是,对于树中的每个节点,其左子树中的所有节点都小于该节点,而右子树中的所有节点都大于该节点。
388 22
|
2月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
266 0
|
2月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
204 2
|
3月前
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
226 3
|
2月前
|
机器学习/深度学习 算法 机器人
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
176 8

热门文章

最新文章