Queue可以从是否阻塞的角度区分为两种,一种是非阻塞queue:AbstractQueue,一种是阻塞Queue:BlockingQueue。在并发队列上JDK提供了两套实现,一个是以ConcurrentLinkedQueue为代表的高性能队列(非阻塞),一个是以BlockingQueue接口为代表的阻塞队列,都是继承自Queue。
Queue接口与List、Set同一级别,都是继承了Collection接口
非阻塞队列
ConcurrentLinkedQueue
add,offer方法都是增加一个元素并返回true,如果队列已满,则返回false。
poll,peek都能获取到队列的头部元素,区别是poll是移除并返回队列头部元素,peek只是返回头部元素并不会移除。
没有put和take,因为ConcurrentLinkedQueue是非阻塞的,而put和take都会导致阻塞。put方法在队列满时阻塞,take方法在队列空时阻塞。
阻塞队列:
LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue、DelayQueue、synchronousQueue
LinkedBlockingQueue
LinkedBlockingQueue的容量是没有上限的(说的不准确,在不指定时容量为Integer.MAX_VALUE,不要然的话在put时怎么会受阻呢),但是也可以选择指定其最大容量,它是基于链表的队列,此队列按 FIFO(先进先出)排序元素。
ArrayBlockingQueue
ArrayBlockingQueue在构造时需要指定容量, 并可以选择是否需要公平性,如果公平参数被设置true,等待时间最长的线程会优先得到处理(其实就是通过将ReentrantLock设置为true来 达到这种公平性的:即等待时间最长的线程会先操作)。通常,公平性会使你在性能上付出代价,只有在的确非常需要的时候再使用它。它是基于数组的阻塞循环队 列,此队列按 FIFO(先进先出)原则对元素进行排序。
PriorityBlockingQueue
PriorityBlockingQueue是一个带优先级的 队列,而不是先进先出队列。元素按优先级顺序被移除,该队列也没有上限(看了一下源码,PriorityBlockingQueue是对 PriorityQueue的再次包装,是基于堆数据结构的,而PriorityQueue是没有容量限制的,与ArrayList一样,所以在优先阻塞 队列上put时是不会受阻的。虽然此队列逻辑上是无界的,但是由于资源被耗尽,所以试图执行添加操作可能会导致 OutOfMemoryError),但是如果队列为空,那么取元素的操作take就会阻塞,所以它的检索操作take是受阻的。另外,往入该队列中的元 素要具有比较能力。
DelayQueue
DelayQueue(基于PriorityQueue来实现的)是一个存放Delayed 元素的无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满,则队列没有头部,并且poll将返回null。当一个元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于或等于零的值时,则出现期满,poll就以移除这个元素了。此队列不允许使用 null 元素。
synchronousQueue
synchronousQueue 没有空间(是一个没有数据缓冲的BlockingQueue),即存即消费。注意在使用offer的之前一定是有一个take方法阻塞在前面。
SynchronousQueue的以下方法:
* iterator() 永远返回空,因为里面没东西。
* peek() 永远返回null。
* put() 往queue放进去一个element以后就一直wait直到有其他thread进来把这个element取走。
* offer() 往queue里放一个element后立即返回,如果碰巧这个element被另一个thread取走了,offer方法返回true,认为offer成功;否则返回false。
* offer(2000, TimeUnit.SECONDS) 往queue里放一个element但是等待指定的时间后才返回,返回的逻辑和offer()方法一样。
* take() 取出并且remove掉queue里的element(认为是在queue里的。。。),取不到东西他会一直等。
* poll() 取出并且remove掉queue里的element(认为是在queue里的。。。),只有到碰巧另外一个线程正在往queue里offer数据或者put数据的时候,该方法才会取到东西。否则立即返回null。
* poll(2000, TimeUnit.SECONDS) 等待指定的时间然后取出并且remove掉queue里的element,其实就是再等其他的thread来往里塞。
* isEmpty()永远是true。
* remainingCapacity() 永远是0。
* remove()和removeAll() 永远是false。