title: 死磕Java队列
date: 2020-05-18 15:53:00
categories: 多线程,Java,Queue,队列
description: Java
1. 概念
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
队列除了保证队列中的元素有序之外,它在基本构造上还在差异,主要体现在 容量 、 阻塞 、 线程安全三个方面。
队列容量:从队列的大小以及容量来说,分为 有界队列、无界队列 。
阻塞:从现场阻塞的特征来说,分为 阻塞队列、非阻塞队列,这决定了队列的吞吐性能。
线程安全:从线程安全来说,分为 线程安全、非线程安全
队列除了上述差异,有的地方还把顺序队列、链式队列以及循环队列这三种队列单独拿出来说。
1.1. 非阻塞队列与阻塞队列
1.1.1. 阻塞队列
支持两个附加操作的队列。这两个附加的操作支持阻塞的 插入
和 移除
方法。具体表现在:
- 队列的容量已满:队列会阻塞插入元素的线程,直到队列不满
- 队列中元素为空:获取元素的线程会等待队列变为非空
生产数据时,若队列已满,那么生产线程会暂停下来,直到队列中有可以存放数据的地方,才会继续工作;而当我们的消费者向队列中获取数据时,若队列为空,则消费者线程会暂停下来,直到容器中有元素出现,才能进行获取操作。
1.1.2. 非阻塞队列
- 队列的容量已满:插入元素抛出异常
- 队列中元素为空:获取元素的为空
1.2. 有界队列与无界队列
有界队列:队列对索要存储元素的上限设置有固定值。队列的容量,队列的容量决定了该队列保存元素的数量上限,这在某些特定场景下,使用 有界队列 可以规避无休止的元素添加而造成内存资源上的开销。
无界队列:队列对索要存储元素的没有设置固定大小,一般理论上的上线就是
Integer.MAX_VALUE
的值,但是从使用者的体验上,就相当于 “无界”。
2. 使用场景
JAVA
中的队列是在 JDK1.5
中被引入,它是一种数据结构,遵循原则就是 FIFO
,即 先进先出
。它的存在就是是为了解决 削峰填谷
,给队列下游减轻压力,将生产速度较快的地方进行减速,以便于适应下游的处理速度。
3. 常用队列
日常使用中一些常用的 JAVA
队列的列表,我们按照是否阻塞、是否线程安全、是否有界作为划分,具体如下:
类名 | 是否阻塞 | 是否线程安全 | 是否有界 | 特点 |
---|---|---|---|---|
LinkedList | 非阻塞 | 线程安全 | 可选有界 | 基于链表 |
ArrayBlockingQueue | 阻塞 | 线程安全 | 有界 | 基于数组的有界队列 |
LinkedBlockingQueue | 阻塞 | 线程安全 | 可选有界 | 基于链表的无界队列 |
ConcurrentLinkedQueue | 非阻塞 | 线程安全 | 无界 | 基于链表 线程安全的队列 |
PriorityBlockingQueue | 阻塞 | 线程安全 | 无界 | 基于优先次序的无界队列 |
PriorityQueue | 非阻塞 | 非线程安全 | 无界 | |
SynchronousQueue | 阻塞 | 线程安全 | 无数据队列 | 内部没有容器的队列 较特别 |
LinkedBlockingQueue | 阻塞 | 线程安全 | 无界 | |
DelayQueue | 阻塞 | 线程安全 | 无界 | 基于时间优先级的队列 |
LinkedTrmsferQueue | 阻塞 | 线程安全 | 无界 | 基于链表 |