- 如上述代码所示,我么们分别展示了非空队列与空队列下
peek的使用,结果如下:

文章插图
阻塞类型[put、take]put
put方法是向队列中添加一个元素,这个方法是阻塞的,也就是说当队列已经满的情况下,再put元素时则会阻塞,直到队列中有空位.
take方法是从队列中获取头节点并且将其移除,这也是一个阻塞方法,当队列中已经没有元素时,take方法则会进入阻塞状态,直到队列中有新的元素进入 。
ArrayBlockingQueue是一个我们常用的典型的有界队列,其内部的实现是基于数组来实现的,我们在创建时需要指定其长度,它的线程安全性由ReentrantLock来实现的 。
public ArrayBlockingQueue(int capacity) {...}public ArrayBlockingQueue(int capacity, boolean fair) {...}- 如上所示,
ArrayBlockingQueue提供的构造函数中,我们需要指定队列的长度,同时我们也可以设置队列是都是公平的,当我们设置了容量后就不能再修改了,符合数组的特性,此队列按照先进先出(FIFO)的原则对元素进行排序 。 - 和
ReentrantLock一样,如果ArrayBlockingQueue被设置为非公平的,那么就存在插队的可能;如果设置为公平的,那么等待了最长时间的线程会被优先处理,其他线程不允许插队,不过这样的公平策略同时会带来一定的性能损耗,因为非公平的吞吐量通常会高于公平的情况 。
- 从它的名字我们可以知道,它是一个由链表实现的队列,这个队列的长度是
Integer.MAX_VALUE,这个值是非常大的,几乎无法达到,对此我们可以认为这个队列基本属于一个无界队列(也又认为是有界队列) 。此队列按照先进先出的顺序进行排序 。
synchronousQueue是一个不存储任何元素的阻塞队列,每一个put操作必须等待take操作,否则不能添加元素 。同时它也支持公平锁和非公平锁 。synchronousQueue的容量并不是1,而是0 。因为它本身不会持有任何元素,它是直接传递的,synchronousQueue会把元素从生产者直接传递给消费者,在这个过程中能够是不需要存储的- 在我们之前介绍过的线程池
CachedThreadPool就是利用了该队列 。Executors.newCachedThreadPool(),因为这个线程池它的最大线程数是Integer.MAX_VALUE,它是更具需求来创建线程,所有的线程都是临时线程,使用完后空闲60秒则被回收,
PriorityBlockingQueue是一个支持优先级排序的无界阻塞队列,可以通过自定义实现compareTo()方法来指定元素的排序规则,或者通过构造器参数Comparator来指定排序规则 。但是需要注意插入队列的对象必须是可比较大小的,也就是Comparable的,否则会抛出ClassCastException异常 。- 它的
take方法在队列为空的时候会阻塞,但是正因为它是无界队列,而且会自动扩容,所以它的队列永远不会满,所以它的put方法永远不会阻塞,添加操作始终都会成功
DelayQueue是一个实现PriorityBlockingQueue的延迟获取的无界队列 。具有“延迟”的功能 。DelayQueue应用场景:1. 缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了 。2. 定时任务调度 。使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的 。- 它是无界队列,放入的元素必须实现
Delayed接口,而Delayed接口又继承了Comparable接口,所以自然就拥有了比较和排序的能力,代码如下:
public interface Delayed extends Comparable<Delayed> {long getDelay(TimeUnit unit);}