Java集合框架-Queue
Queue简介
Java集合框架中的队列来自于最基本的Queue接口:
public interface Queue<E> extends Collection<E> {
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
}
-
add/offer
添加元素,add
等同于Collection
中的add
方法,队列满了之后调用add
方法会抛出异常,offer
则返回false表示添加失败 -
remove/poll
删除第一个元素,remove
等同于Collection
中的remove
方法,队列为空以后调用会抛出异常,而poll
会返回null
-
element/peek
查询头部元素,同上,但是不移除元素。
util包中的Queue
Java中常用的队列分为两种,一种是util包中的常规队列,主要包括PriorityQueue,ArrayDeque
。
PriorityQueue
-
PriorityQueue
是有序队列,数据存放顺序由指定的Comparator
(如果有)或自然排序决定,而不是插入时的顺序。 -
PriorityQueue
不能插入null
值,会抛出异常 -
PriorityQueue
采用数组存储数据,没有同步方法,是线程不安全的。
ArrayDequeue
ArrayDequeue
是双端队列,继承了Dequeue
接口,除了Queue
中的方法之外,它还有一些addFirst/ offerFirst
,removeLast/pollLast
等指定头尾的操作。
它内部也是采用数组存储数据,存储顺序为插入顺序,同样不能接受null值,并且线程不安全
Concurrent包中的Queue
Concurrent
包中又分为两类队列,一类是阻塞队列,实现了BlockingQueue
接口,另一类是非阻塞队列,只是加了同步。
非阻塞队列
非阻塞队列有ConcurrentLinkedDeque
和ConcurrentLinkedQeque
,一个单端一个双端队列,都是先进先出原则,不会阻塞,线程安全
阻塞队列
-
ArrayBlockingQueue
数组实现的有界队列,必须指定容量,可以实现公平锁或非公平锁,默认非公平锁 -
LinkedBlockingQueue
链表实现的有界队列,默认容量为MAX。采用链表存储的方式,在添加移除数据时会产生大量的node节点对象,内存消耗比数组要严重。LinkedBlockingQueue
的put
和take
锁是分离的,多线程读写效率比ArrayBlockingQueue
要高。 -
LinkedBlockingDeque
同上,双端队列 -
PriorityBlockingQueue
*的有序队列,按照指定的Comparator
或自然排序存储数据,默认初始容量为11,可以指定初始容量,存满后自动扩容。 -
SynchronousQueue
不存储元素,每一个put
操作都要等待take
取走数据之后才能进行 -
DelayQueue
延时队列 LinkedTransferQueue
他们都继承自BlockingQueue
接口:
public interface BlockingQueue<E> extends Queue<E> {
boolean add(E e);
boolean offer(E e);
void put(E e) throws InterruptedException;
boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException;
E take() throws InterruptedException;
E poll(long timeout, TimeUnit unit)
throws InterruptedException;
boolean remove(Object o);
}
除了继承自Queue
接口的方法以外,它新增了阻塞方法,put
和take
,另外新增了可以指定超时时间的offer
和poll
方法。
延时队列DelayQueue
:
它内部采用了PriorityBlockingQueue
存储数据,按照延时时间的顺序来存放。存放元素必须是实现了Delayed
接口的对象。Delayed
接口本身只有一个方法,另外它还继承了Comparable
,也就是说它的存储对象必须实现以下两个方法:
long getDelay(TimeUnit unit);
public int compareTo(T o);
getDelay
返回值为long
类型,只有当返回值小于等于0的时候,才认为该元素的延时时间已经结束,可以被取出了,如果所有元素都处于等待状态,那么取出的值为null。compareTo
决定了元素存放的顺序,通常是按delay时间升序排列。
LinkedTransferQueue
:
除了阻塞队列的通用方法之外,它多了一个transfer
功能:
transfer(E e):若当前存在一个正在等待获取的消费者线程,即立刻移交;否则,会插入当前元素e到队列尾部,并且进入阻塞状态,直到有消费者线程取走该元素。
tryTransfer(E e):若当前存在一个正在等待获取的消费者线程(take()或者poll()),使用该方法会即刻转移/传输对象元素e;若不存在,则返回false,并且数据不插入队列,非阻塞方法。
tryTransfer(E e, long timeout, TimeUnit unit):若当前存在一个正在等待获取的消费者线程,会立即传输给它;否则将插入元素e到队列尾部,并且等待被消费者线程获取消费掉;若在指定的时间内元素e无法被消费者线程获取,则返回false,同时该元素被移除。
hasWaitingConsumer():判断是否存在消费者线程。
getWaitingConsumerCount():获取所有等待获取元素的消费线程数量。
上一篇: 数组实现循环队列
下一篇: JAVA集合学习Queue