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方法,隊列滿了之后調(diào)用add方法會拋出異常,offer則返回false表示添加失敗
  • remove/poll 刪除第一個元素,remove等同于Collection中的remove方法,隊列為空以后調(diào)用會拋出異常,而poll會返回null
  • element/peek 查詢頭部元素,同上,但是不移除元素。

util包中的Queue

Java中常用的隊列分為兩種,一種是util包中的常規(guī)隊列,主要包括PriorityQueue,ArrayDeque。

PriorityQueue

  1. PriorityQueue是有序隊列,數(shù)據(jù)存放順序由指定的Comparator(如果有)或自然排序決定,而不是插入時的順序。
  2. PriorityQueue不能插入null值,會拋出異常
  3. PriorityQueue采用數(shù)組存儲數(shù)據(jù),沒有同步方法,是線程不安全的。

ArrayDequeue

ArrayDequeue是雙端隊列,繼承了Dequeue接口,除了Queue中的方法之外,它還有一些addFirst/ offerFirst,removeLast/pollLast 等指定頭尾的操作。
它內(nèi)部也是采用數(shù)組存儲數(shù)據(jù),存儲順序為插入順序,同樣不能接受null值,并且線程不安全

Concurrent包中的Queue

Concurrent包中又分為兩類隊列,一類是阻塞隊列,實現(xiàn)了BlockingQueue接口,另一類是非阻塞隊列,只是加了同步。

非阻塞隊列

非阻塞隊列有ConcurrentLinkedDequeConcurrentLinkedQeque,一個單端一個雙端隊列,都是先進先出原則,不會阻塞,線程安全

阻塞隊列

  • ArrayBlockingQueue 數(shù)組實現(xiàn)的有界隊列,必須指定容量,可以實現(xiàn)公平鎖或非公平鎖,默認非公平鎖
  • LinkedBlockingQueue 鏈表實現(xiàn)的有界隊列,默認容量為MAX。采用鏈表存儲的方式,在添加移除數(shù)據(jù)時會產(chǎn)生大量的node節(jié)點對象,內(nèi)存消耗比數(shù)組要嚴重。LinkedBlockingQueueputtake鎖是分離的,多線程讀寫效率比ArrayBlockingQueue要高。
  • LinkedBlockingDeque同上,雙端隊列
  • PriorityBlockingQueue 無界的有序隊列,按照指定的Comparator或自然排序存儲數(shù)據(jù),默認初始容量為11,可以指定初始容量,存滿后自動擴容。
  • SynchronousQueue 不存儲元素,每一個put操作都要等待take取走數(shù)據(jù)之后才能進行
  • 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接口的方法以外,它新增了阻塞方法,puttake,另外新增了可以指定超時時間的offerpoll方法。

延時隊列DelayQueue

它內(nèi)部采用了PriorityBlockingQueue存儲數(shù)據(jù),按照延時時間的順序來存放。存放元素必須是實現(xiàn)了Delayed接口的對象。Delayed接口本身只有一個方法,另外它還繼承了Comparable,也就是說它的存儲對象必須實現(xiàn)以下兩個方法:

long getDelay(TimeUnit unit);
public int compareTo(T o);

getDelay返回值為long類型,只有當返回值小于等于0的時候,才認為該元素的延時時間已經(jīng)結束,可以被取出了,如果所有元素都處于等待狀態(tài),那么取出的值為null。
compareTo決定了元素存放的順序,通常是按delay時間升序排列。

LinkedTransferQueue:

除了阻塞隊列的通用方法之外,它多了一個transfer功能:

  • transfer(E e):若當前存在一個正在等待獲取的消費者線程,即立刻移交;否則,會插入當前元素e到隊列尾部,并且進入阻塞狀態(tài),直到有消費者線程取走該元素。

  • tryTransfer(E e):若當前存在一個正在等待獲取的消費者線程(take()或者poll()),使用該方法會即刻轉(zhuǎn)移/傳輸對象元素e;若不存在,則返回false,并且數(shù)據(jù)不插入隊列,非阻塞方法。

  • tryTransfer(E e, long timeout, TimeUnit unit):若當前存在一個正在等待獲取的消費者線程,會立即傳輸給它;否則將插入元素e到隊列尾部,并且等待被消費者線程獲取消費掉;若在指定的時間內(nèi)元素e無法被消費者線程獲取,則返回false,同時該元素被移除。

  • hasWaitingConsumer():判斷是否存在消費者線程。

  • getWaitingConsumerCount():獲取所有等待獲取元素的消費線程數(shù)量。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容