BlockingQueue的概述
声明:仅仅对比介绍下BlockingQueue和其各个子接口与实现类
基接口BlockingQueue<E>
-
概述
-
BlockingQueue
位于java.util.concurrent
包下面,是一个为了应对并发情况的队列的接口,其实现类都是线程安全的。 - 除去集合类提供的批量操作,如
addAll
、containsAll
、retainAll
、removeAll
,这些方法可以不必是原子性的以外,其他操作都是原子性的。 -
BlockingQueue
不接受null
元素,如果尝试插入(add
、put
、offer
)null
元素,将会抛出空指针异常。因为在poll
方法中,返回null
值被认为是操作失败的表现。 -
BlockingQueue
可能是有容量限制的,如果没有定义指定的容量,则其容量应为Integer.MAX_VALUE
-
BlockingQueue
继承了Collection
,所以能够在队列中使用remove
这种较为暴力的方法直接去除存在的元素,但是该方法在队列中执行效率很差,只可在特定的场合下使用。 -
BlockingQueue
有多种插入(包括入列)、移除(包括出列)、查看的方法,每种方法在操作失败时候的具体行为各不相同,具体见表
抛出异常 返回false/null 阻塞 带超时的阻塞 插入 add(e)
offer(e)
put(e)
offer(e, time, unit)
移除 remove()
poll()
take()
poll(time, unit)
查看 element()
peek()
\ \ -
-
常见方法
-
add
方法,插入一个元素,成功返回true,失败抛出异常 -
offer
方法,插入一个元素,成功返回true,失败返回false -
put
方法,插入一个元素,阻塞直到队列中有控件可以操作 -
remove(Object)
方法,直接从队列中去除一个指定元素 -
remove
方法,去除头部元素并返回该元素,如果队列空则抛出异常 -
poll
方法,去除头部元素并返回该元素,如果队列空则返回null -
take
方法,去除头部元素并返回该元素,如果队列为空则阻塞直到队列中有元素 -
element
方法,仅仅只返回头部元素,队列为空抛出异常 -
peek
方法,仅仅只返回头部元素,队列为空返回null -
remainingCapacity
方法,返回剩余空间数 -
drainTo(Collection)
方法,移除所有元素到一个集合中
-
-
子接口
- TransferQueue
-
与
SynchronnousQueue
不同的是,插入时不需要任何等待,直接插入队列,但是会阻塞到直到有一个线程尝试从队列中取出元素 -
注意,取出的方法必须是
take
方法或者是带时限的poll
方法,因为只有这些方法会在尝试取出元素时进行一定时间的等待,SynchronnousQueue
部分也适用这个警告 -
常见方法:
-
transfer
方法,直接插入一个元素进队列,但是会阻塞直到有一个线程尝试从队列中取出这个元素 -
tryTransfer
方法,如果没有等待着的消费者,则返回false
,且不会插入元素 -
getWaitingConsumerCount
-
hasWaitingConsumer
-
-
实现类
-
LinkedTransferQueue
介绍:略
-
-
- BlockingDeque
- 并发的双端队列
-
实现类
-
LinkedBlockingDeque
介绍:略
-
- TransferQueue
-
实现类
-
ArrayBlockingQueue
-
由数组支持的
BlockingQueue
,容量大小是固定的,需要在构造时指定,且不可更改 -
提供一个可选的“公平政策”标识,如果该标识为
false
(默认)则队列不会维护都处于等待状态的生产者/消费者的顺序,反之则会维护他们到来的顺序 -
支持以集合的方式初始化最初的队列
-
-
LinkedBlockingQueue
-
由链表支持的
BlockingQueue
,容量大小可以指定,默认值是Integer.MAX_VALUE
,实际大小则是动态的 -
支持以集合的方式初始化最初的队列
-
在高并发的情况下的可预测性不如
ArrayBlokingQueue
-
-
PriorityBlockingQueue
-
按照元素实现的
Compareable
接口比较而得到的顺序作为队列中元素的排列顺序,所以如果插入的元素不是实现Cpmpareable
接口的,将会抛出类型转换异常 -
其
iterator
方法并不会按照该类的顺序规则来遍历,如果想要实现这种效果可以尝试使用Arrays.sort(pbq.toArray)
-
drainTo
和toArray
方法都支持按该类的顺序规则来输出元素 -
如果两个元素比较相等,则他们的实际排列顺序是不定的
-
默认初始化容量为11,但是实际容量会不断增加,没有上限,除非资源不足
-
-
SynchronousQueue
-
该队列的插入/取出,仅仅只会发生在另一个线程尝试对这个队列进行取出/插入时,所以如果只有一个线程想要插入,那么该线程会阻塞,直到有另一个线程想要取出
-
由于上诉特性,
peek
、element
方法将没有意义,将会直接返回失败状态,同理的还有size
方法、reamingCapacity
、isEmpty
、toArray
、contains
、containsAll
、iterator
方法等等,因为实际上队列中就是空的 -
提供一个可选的“公平政策”标识,如果该标识为
false
(默认)则队列不会维护都处于等待状态的生产/消费者的顺序,反之会维护他们到来的顺序
-
-
DelayQueue
-
延迟队列,所有的插入元素必须实现
Delayed
接口,元素从被插入到队列的那一刻开始便进行倒计时,直到延迟时间结束,该元素才算“真正”显示在队列里 -
延迟队列的元素排列顺序是按照元素延迟时间结束的早晚来定的,表头元素是整个队列中最早结束延迟的元素
-
如果在全元素都还在延迟的状态下,尝试取出元素,效果和从空队列取出元素一样
-
但是毕竟元素是真正在队列中的,调用
size
方法会返回队列中所有元素的数量,无论是否延迟结束
-
-
ConcurrentLinkedQueue
- 也是位于并发包下的一个并发队列,效率比之
BlockingQueue
要高,前者适用于不太在意元素顺序,高并发的情况,后者适用于保证元素在多线程下的顺序的情况,会有阻塞的情况。 - 同样不接受
null
元素 - 遍历及获取队列长度的结果是不一定准确的
-
addAll
,removeAll
,retainAll
,containsAll
,equals
,toArray
这些方法不是原子的
参考文档: