队列是程序中十分重要的一种数据结构,这篇文章就对Java中的队列进行梳理介绍。该篇文章主要从队列的概念入手,后续再从源码角度刨析写一篇文章。
一、定义
(1)特性:先进先出(FIFO)
(2)底层结构:数组
+链表
二、关系图
三、分类
1、阻塞队列
(1)ArrayBlockingQueue有界队列
ArrayBlockingQueue是用数组实现的有界阻塞队列
。这种队列中的元素按FIFO(先进先出)排序。队头是在队列中停留最长时间的元素。队尾是在队列中停留时间最短的元素。新元素插入到队列的尾部,并且队列检索操作在队列的头部获取元素。
这是一个经典的“有界缓冲区”,其中固定大小的数组包含由生产者插入并由消费者提取的元素。创建后,容量将无法更改。试图将一个元素放入一个已满的队列将导致操作阻塞;试图从空队列中取出一个元素也会阻塞。
这个类支持一个可选的公平性策略,用于对等待的生产者和消费者线程进行排序。默认情况下,不保证这个顺序。然而,将公平性设置为true的队列将按FIFO顺序授予线程访问权。公平性通常会降低吞吐量,但会降低可变性并避免饥饿。
(2)LinkedBlockingQueue无界队列
LinkedBlockingQueue是一个基于链表实现的可选边界的阻塞队列
。
“有界”的阻塞安全队列,其底层使用的是链表的数据结构。所谓的“有界”是因为,默认队列的大小是Integer.MAX_VALUE。这个数值等于21亿+。因为这个数据太大了,也可以理解为无界的。不建议使用默认值,最好在初始化的时候,指定队列的大小。
(3)PriorityBlockingQueue
PriorityBlockingQueue是一个无界阻塞队列
,它使用与PriorityQueue相同的排序规则,并提供阻塞检索操作。是一个支持优先级的无界队列。支持优先级是因为使用了comparator这个接口。默认采用字典升序排序策略的。如果不想使用默认的,在初始化的时候,还可以自定义比较器的。
(4)DelayQueue
是一个支持优先级的无界阻塞队列
。支持优先级是应该底层使用的是PriorityQueue队列来实现的。而PriorityQueue队列在添加元素的时候使用了siftUpComparable方法。这个队列的一个特点:支持延时获取。所以,这个队列可以运用在缓存系统的设计中。当从队列中获取到数据,说明延时时间到了。
(5)SynchronouseQueue同步队列
是一个无存储空间的阻塞同步队列
。不存储元素的原因是因为,一个put操作必须等待一个take操作与之对应才可以。否则就不能继续添加元素了。默认使用非公平的。在性能上SyncQueue队列的吞吐量比LBqueu和ABQueue的性能高。
(6)LinkedTrnsferQueue
由链表组成的无界队列
。比其他队列多了两个方法:tryTransfer、transfer。
(7)LinkedBlockingDeque
链表组成的双端队列
。For/Join框架中有涉及到这个队列。
2、非阻塞队列
(1)ConcurrentLinkedQueue
(2)PriorityQueue(优先级队列)
PriorityQueue是一个无界优先级队列
是基于优先级的。优先级队列中的元素根据自然顺序进行排序,或者通过在队列构建时提供的Comparator进行排序,当然这取决于使用哪种构造函数。优先级队列不允许空(null)元素。一个依赖自然顺序的优先级队列也不允许插入不可比较的对象。
PriorityQueue的队头元素是最小的元素
,如果有多个元素并列最小,那么队头是它们其中之一。
PriorityQueue是无界
的,但是有一个内部容量来控制用于在队列上存储元素的数组的大小。它总是至少与队列大小一样大。将元素添加到优先级队列时,其容量会自动增长。
3、双端队列
Deque(double-ended queue,双端队列)是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。
四、AbstractQueuedSynchronizer
AbstractQueuedSynchronizer提供了一个框架来实现依赖于先进先出(FIFO)等待队列的阻塞锁和相关的同步器(信号灯,事件等)。
该类旨在为大多数依赖单个原子int值表示状态的同步器提供有用的基础。子类必须定义更改此状态的受保护方法,并定义该状态对于获取或释放此对象而言意味着什么。
鉴于这些,此类中的其他方法将执行所有排队和阻塞机制。子类可以维护其他状态字段,但是仅跟踪关于同步的使用方法getState(),setState(int)和compareAndSetState(int,int)操作的原子更新的int值。
五、小结
1、Queue是一个集合,队列的每个方法都有两种形式,一种是抛异常,另一种是返回一个特定的值。
2、PriorityQueue是一个无界优先级队列,默认情况下,队列中的元素按自然顺序排序,或者根据提供的Comparator进行排序。也就是说,优先级队列中的元素都是经过排序的,排序规则可以自己指定,同时队列中的元素都必须是可排序的。
3、BlockingQueue是一个阻塞队列,向已满的队列中插入元素时会阻塞,向空队列中取元素时也会阻塞;阻塞队列被设计主要用于生产者-消费者队列。
4、ArrayBlockingQueue是用数组实现的有界阻塞队列,队列中的元素按FIFO(先进先出)排序。
5、LinkedBlockingQueue是用链表实现的可选边界的阻塞队列。
6、PriorityBlockingQueue相当于是阻塞队列和优先级队列的合体,排序规则与优先级队列相同。
7、DelayQueue延时队列中的元素都有一个有效期,只有当过了有效期才可以使用该元素。
参考文章:
《Java 中的各种队列使用总结》