阻塞队列简介
阻塞队列是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移出方法。
- 支持阻塞的插入方法:意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满
- 支持阻塞的移出方法:意思是当队列为空时,获取元素的线程会等待队列变成非空
在阻塞队列不可用时,这两个附加操作提供了4种处理方式:

- 抛出异常:当队列满时,如果再往队列里擦汗如元素,会抛出IllegalStateException(“Queue Fulll”)异常。当队列空时,从队列里获取元素会抛出NoSuchElementException异常
- 返回特殊值:当往队列插入元素时,会返回元素是否插入成功,成功返回true。如果是移除方法,则是从队列里取出一个元素,如果没有则返回null
- 一直阻塞:当阻塞队列满时,如果生产者线程往队列里put元素,队列会一直阻塞生产者线程,直到队列可用或者响应中断推出。当队列空时,如果消费者线程从队列里take元素,队列会阻塞住消费者线程,直到队列不为空
- 超时推出:当阻塞队列满时,如果生产者线程往队列里插入元素,队列会阻塞生产者线程一段时间,如果超过了指定时间,生产者线程就会退出
Java里的阻塞队列
JDK7提供了7个阻塞队列
- ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列
- LinkedBlockingQueue:一个由链表组成的有界阻塞队列。此队列的默认和最大长度为Interger.MAX_VALUE
- PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。默认情况管辖元素采取自然顺序,升序排列。也可以自定义类实现compareTo()方法来指定元素排序规则
- DelayQueue:一个使用优先级队列实现的无阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素(常用于缓存有效期,定时任务调度等场景)
- SynchronousQueue:一个不存储元素的阻塞队列。每一个put操作必须等待一个take操作,否则不能继续添加元素。队列本身不存储任何元素,非常适合传递性场景
- LinkedTransferQueue:一个由链表结构组成的单向无界阻塞队列。它设计了一种直接在生产者和消费者之间传输元素的机制,成为“transfer”。当生产者调用transfer(e)方法时,它会阻塞直到有一个消费者接收该元素。适用于徐娅高效地在生产者和消费者之间直接传输数据的场景,尤其是当生产者和消费者之间的速度大致匹配时
- LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。所谓双向队列指的是可以从队列的两端插入和移出元素。相比其他的阻塞队列,LinkedBlockingDeque多了addFirst、addLast、offer-First、offerLast、peekFirst和peekLast等方法。双向阻塞队列可以运用在“工作窃取”模式中。
阻塞队列的实现原理
如果队列是空的,消费者会一直等待,当生产者添加元素时,消费者是如何知道当前队列有元素的呢?
使用通知模式实现。所谓通知模式,当消费者从空的队列获取元素时,会阻塞住消费者,此时如果生产者放了一个元素进入队列,则需要通知阻塞住消费者当前有元素可取。同理当生产者往满的队列里添加元素时会阻塞住生产者,当消费者消费了一个队列中的元素后,会通知生产者当前队列可用
通过查看源码可知ArrayBlockingQueue使用了Condition来实现上述效果