Java 集合系列之四:Queue基本操作


1. Java Queue

1. Java Queue 重要觀點

  • Java Queue接口是Java Collections Framework的成員。
  • Queue 實現通常不允許插入 null 元素
  • 隊列通常(但並非一定)以 FIFO(先進先出)的方式排序各個元素。不過優先級隊列和 LIFO 隊列(或堆棧)例外,前者根據提供的比較器或元素的自然順序對元素進行排序,后者按 LIFO(后進先出)的方式對元素進行排序。無論使用哪種排序方式,隊列的 都是調用 remove() 或 poll() 所移除的元素。在 FIFO 隊列中,所有的新元素都插入隊列的末尾。其他種類的隊列可能使用不同的元素放置規則。每個 Queue 實現必須指定其順序屬性。
  • 在處理元素前用於保存元素的 collection。除了基本的 Collection 操作外,隊列還提供其他的插入、提取和檢查操作。每個方法都存在兩種形式:一種拋出異常(操作失敗時),另一種返回一個特殊值(null 或 false,具體取決於操作)。
  • Queue 接口並未定義阻塞隊列的方法,而這在並發編程中是很常見的。BlockingQueue 接口定義了那些等待元素出現或等待隊列中有可用空間的方法,這些方法擴展了此接口。
  •   拋出異常   返回特殊值
    插入:add(e)     offer(e)  插入一個元素
    移除:remove()      poll()      移除和返回隊列的頭
    檢查:element()     peek()    返回但不移除隊列的頭。

  • JDK中並發隊列提供了兩種實現,一種是高性能隊列ConcurrentLinkedQueue,一種是阻塞隊列BlockingQueue(7種阻塞隊列),兩種都繼承自Queue。
  • JDK中隊列有兩大類,一類是雙端隊列,一類是單端隊列。

2. Java Queue類圖

此接口是 Java Collections Framework 的成員。

Java Queue接口擴展了Collection接口。Collection接口 externs Iterable接口。

子接口:BlockingQueue, Deque, BlobkingDequeue

一些最常用的Queue實現類是LinkedList,ArrayBlickingQueue, LinkedBlockingQueue,PriorityQueue, PriorityBlockingQueue。

3. Java Queue 方法

boolean  add(E e) //將指定的元素插入此隊列(如果立即可行且不會違反容量限制),在成功時返回 true,如果當前沒有可用的空間,則拋出 IllegalStateException。
E        element() //獲取,但是不移除此隊列的頭。
boolean  offer(E e) //將指定的元素插入此隊列(如果立即可行且不會違反容量限制),當使用有容量限制的隊列時,此方法通常要優於 add(E),后者可能無法插入元素,而只是拋出一個異常。
E        peek() //獲取但不移除此隊列的頭;如果此隊列為空,則返回 null。
E        poll() //獲取並移除此隊列的頭,如果此隊列為空,則返回 null。
E        remove() //獲取並移除此隊列的頭。

2. ConcurrentLinkedQueue接口(JUC)

1. ConcurrentLinkedQueue 結構圖

一個基於鏈接節點的無界線程安全隊列。

2. ConcurrentLinkedQueue重要特點

  1. 一個基於鏈接節點的無界線程安全隊列。此隊列按照 FIFO(先進先出)原則對元素進行排序。隊列的頭部 是隊列中時間最長的元素。隊列的尾部是隊列中時間最短的元素。新的元素插入到隊列的尾部,隊列獲取操作從隊列頭部獲得元素。當多個線程共享訪問一個公共 collection 時,ConcurrentLinkedQueue 是一個恰當的選擇。

  2. 此隊列不允許使用 null 元素。

  3. 此實現采用了有效的“無等待 (wait-free)”算法,該算法基於 Maged M. Michael 和 Michael L. Scott 合著的 Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms 中描述的算法。

  4. 需要小心的是,與大多數 collection 不同,size 方法不是 一個固定時間操作。由於這些隊列的異步特性,確定當前元素的數量需要遍歷這些元素。

  5. 內存一致性效果:當存在其他並發 collection 時,將對象放入 ConcurrentLinkedQueue 之前的線程中的操作 happen-before 隨后通過另一線程從 ConcurrentLinkedQueue 訪問或移除該元素的操作。
  6. ConcurrentLinkedQueue中有兩個volatile類型的Node節點分別用來存在列表的首尾節點,其中head節點存放鏈表第一個item為null的節點,tail則並不是總指向最后一個節點。Node節點內部則維護一個變量item用來存放節點的值,next用來存放下一個節點,從而鏈接為一個單向無界列表。
  7. 開源框架中使用:Tomcat中NioEndPoint中的每個poller里面就維護一個ConcurrentLinkedQueue<Runnable>用來作為緩沖存放任務。
  8. ConcurrentLinkedQueue使用CAS非阻塞算法實現使用CAS解決了當前節點與next節點之間的安全鏈接和對當前節點值的賦值。【CAS的基本思想是認為當前環境中的並發並沒有那么高,比較樂觀的看待整個並發,只需要在更新某個值時先檢查下該值有沒有發生變化,如果沒有發生變化則更新,否則放棄更新。CAS的操作其底層是通過調用sun.misc.Unsafe類中的CompareAndSwap的方法保證線程安全的。】由於使用CAS沒有使用鎖,所以獲取size的時候有可能進行offer,poll或者remove操作,導致獲取的元素個數不精確,所以在並發情況下size函數不是很有用。另外第一次peek或者first時候會把head指向第一個真正的隊列元素。
  9. 線程安全的volatile + CAS 可知入隊出隊函數都是操作volatile變量:head,tail所以要保證隊列線程安全只需要保證對這兩個Node操作的可見性和原子性,由於volatile本身保證可見性,所以只需要看下多線程下如果保證對着兩個變量操作的原子性。對於offer操作是在tail后面添加元素,也就是調用tail.casNext方法,而這個方法是使用的CAS操作,只有一個線程會成功,然后失敗的線程會循環一下,重新獲取tail,然后執行casNext方法。對於poll也是這樣的。

3. Deque接口

1. Deque結構圖

 

  一個線性 collection,支持在兩端插入和移除元素。名稱 deque 是“double ended queue(雙端隊列)”的縮寫,通常讀為“deck”。大多數 Deque 實現對於它們能夠包含的元素數沒有固定限制,但此接口既支持有容量限制的雙端隊列,也支持沒有固定大小限制的雙端隊列。

  隊列:此接口擴展了 Queue 接口。在將雙端隊列用作隊列時,將得到 FIFO(先進先出)行為。將元素添加到雙端隊列的末尾,從雙端隊列的開頭移除元素。

  堆棧:雙端隊列也可用作 LIFO(后進先出)堆棧。應優先使用此接口而不是遺留 Stack 類。在將雙端隊列用作堆棧時,元素被推入雙端隊列的開頭並從雙端隊列開頭彈出。堆棧方法完全等效於 Deque 方法,

4. LinkedList

1. LinkedList 結構圖

LinkedList是基於鏈表實現的,從源碼可以看出是一個雙向鏈表。除了當做鏈表使用外,它也可以被當作堆棧、隊列或雙端隊列進行操作

LinkedList不是線程安全的,繼承AbstractSequentialList實現List、Deque、Cloneable、Serializable。

  • LinkedList繼承AbstractSequentialList,AbstractSequentialList 實現了get(int index)、set(int index, E element)、add(int index, E element) 和 remove(int index)這些函數。這些接口都是隨機訪問List的。
  • LinkedList 實現 List 接口,能對它進行隊列操作。
  • LinkedList 實現 Deque 接口,即能將LinkedList當作雙端隊列使用。
  • LinkedList 實現了Cloneable接口,即覆蓋了函數clone(),能克隆。
  • LinkedList 實現java.io.Serializable接口,這意味着LinkedList支持序列化,能通過序列化去傳輸。

2. LinkedList 重要特點

  1. 本質實現:底層使用一個Node數據結構,有前后兩個指針,雙向鏈表實現。
  2. 線程安全:非同步的。
  3. 列表長度:LinkedList中元素個數用size記錄。
  4. 列表容量:LinkedList是基於鏈表實現的,因此不存在容量不足的問題,所以這里沒有擴容的方法。
  5. 內存:需要更多的內存,LinkedList 每個節點中需要多存儲前后節點的信息,占用空間更多些(previous  element next)。
  6. 元素允許為null。
  7. Fail-Fast機制:同ArrayList相同。
  8. 遍歷方法:所有指定位置的操作都是從頭開始遍歷進行的。LinkedList是基於鏈表實現的,因此插入刪除效率高,查找效率低(雖然有一個加速動作)。源碼中先將index與長度size的一半比較,如果index<size/2,就只從位置0往后遍歷到位置index處,而如果index>size/2,就只從位置size往前遍歷到位置index處。這樣可以減少一部分不必要的遍歷,從而提高一定的效率(實際上效率還是很低)。Arrays.copyOf() 方法:
  9. 它適合刪除,插入較多的場景。

5. ConcurrentLinkedDeque接口(JUC)

1. ConcurrentLinkedDeque 結構圖

並發隊列ConcurrentLinkedDeque,這是一個非阻塞,無鎖,無界 ,線程安全雙端操作的隊列。簡單說就是ConcurrentLinkedQueue的升級版,在JDK7之后才提供。該隊列也不允許空元素,而且size方法並不是常量時間,其需要遍歷鏈表,此時並發修改鏈表會造成統計size不正確。同樣,bulk操作和equal以及toArray方法不保證原子性。

2. ConcurrentLinkedDeque重要特點

  1. ConcurrentLinkedDeque 是 雙向鏈表結構的無界並發隊列。從JDK 7開始加入到J.U.C的行列中。
  2. 使用 CAS實現並發安全,與 ConcurrentLinkedQueue 的區別是 該阻塞隊列同時支持FIFOFILO兩種操作方式,即可以從隊列的頭和尾同時操作(插入/刪除)。
  3. 適合“多生產,多消費”的場景
  4. 內存一致性遵循對 ConcurrentLinkedDeque 的插入操作先行發生於(happen-before)訪問或移除操作

6. BlockingQueue接口(JUC)

1. BlockingQueue 結構圖

JDK7提供了7個阻塞隊列。分別是

  • ArrayBlockingQueue :一個由數組結構組成的有界阻塞隊列。
  • LinkedBlockingQueue :一個由鏈表結構組成的可選有界阻塞隊列。如果未指定容量,那么容量將等於 Integer.MAX_VALUE。 2 31-1 
  • PriorityBlockingQueue :一個支持優先級排序的無界阻塞隊列。
  • DelayQueue:一個使用優先級隊列實現的無界阻塞隊列,,只有在延遲期滿時才能從中提取元素。
  • SynchronousQueue:一個不存儲元素、沒有內部容量的阻塞隊列。
  • LinkedTransferQueue:一個由鏈表結構組成的無界阻塞TransferQueue隊列。
  • LinkedBlockingDeque:一個由鏈表結構組成的可選范圍雙向阻塞隊列。如果未指定容量,那么容量將等於 Integer.MAX_VALUE。 2 31-1 

2. BlockingQueue重要特點

  1. 支持兩個附加操作的 Queue,這兩個操作是:獲取元素時等待隊列變為非空,以及存儲元素時等待空間變得可用(阻塞)。
  2. BlockingQueue 方法以四種形式出現,對於不能立即滿足但可能在將來某一時刻可以滿足的操作,這四種形式的處理方式不同:第一種是拋出一個異常,第二種是返回一個特殊值(null 或 false,具體取決於操作),第三種是在操作可以成功前,無限期地阻塞當前線程,第四種是在放棄前只在給定的最大時間限制內阻塞。下表中總結了這些方法:
  3. BlockingQueue 不接受 null 元素。試圖 addput 或 offer 一個 null 元素時,某些實現會拋出 NullPointerExceptionnull 被用作指示 poll 操作失敗的警戒值。

  4.  BlockingQueue 可以是限定容量的。它在任意給定時間都可以有一個 remainingCapacity超出此容量,便無法無阻塞地 put 附加元素。沒有任何內部容量約束的 BlockingQueue 總是報告 Integer.MAX_VALUE 的剩余容量。

  5.  BlockingQueue 實現主要用於生產者-使用者隊列BlockingQueue 可以安全地與多個生產者和多個使用者一起使用。但它另外還支持 Collection 接口。因此,舉例來說,使用 remove(x) 從隊列中移除任意一個元素是有可能的。然而,這種操作通常 會有效執行,只能有計划地偶爾使用,比如在取消排隊信息時。

  6.  BlockingQueue 實現是線程安全的。所有排隊方法都可以使用內部鎖或其他形式的並發控制來自動達到它們的目的。然而,大量的 Collection 操作(addAllcontainsAllretainAll 和 removeAll沒有 必要自動執行,除非在實現中特別說明。因此,舉例來說,在只添加了 c 中的一些元素后,addAll(c) 有可能失敗(拋出一個異常)。

  7. BlockingQueue 實質上 支持使用任何一種“close”或“shutdown”操作來指示不再添加任何項。這種功能的需求和使用有依賴於實現的傾向。例如,一種常用的策略是:對於生產者,插入特殊的 end-of-stream 或 poison 對象,並根據使用者獲取這些對象的時間來對它們進行解釋。

  8. 內存一致性效果:當存在其他並發 collection 時,將對象放入 BlockingQueue 之前的線程中的操作 happen-before 隨后通過另一線程從 BlockingQueue中訪問或移除該元素的操作。

7. ArrayBlockingQueue(JUC)

1. ArrayBlockingQueue 結構圖

2. ArrayBlockingQueue 重要特點

  1. 一個由數組支持的有界阻塞隊列。此隊列按 FIFO(先進先出)原則對元素進行排序。隊列的頭部 是在隊列中存在時間最長的元素。隊列的尾部 是在隊列中存在時間最短的元素。新元素插入到隊列的尾部,隊列獲取操作則是從隊列頭部開始獲得元素。

  2. 這是一個典型的“有界緩存區”,固定大小的數組在其中保持生產者插入的元素和使用者提取的元素。一旦創建了這樣的緩存區,就不能再增加其容量。試圖向已滿隊列中放入元素會導致操作受阻塞;試圖從空隊列中提取元素將導致類似阻塞。

  3. 此類支持對等待的生產者線程和使用者線程進行排序的可選公平策略。默認情況下,不保證是這種排序。然而,通過將公平性 (fairness) 設置為 true 而構造的隊列允許按照 FIFO 順序訪問線程。公平性通常會降低吞吐量,但也減少了可變性和避免了“不平衡性”。

  4. ArrayBlockingQueue內部有個循環數組items用來存放隊列元素,putIndex下標標示入隊元素下標,takeIndex是出隊下標,count統計隊列元素個數,從定義可知道並沒有使用volatile修飾,這是因為訪問這些變量使用都是在鎖塊內,並不存在可見性問題。

  5. 有個獨占鎖lock用來對出入隊操作加鎖,這導致同時只有一個線程可以訪問入隊出隊,

  6. notEmpty,notFull條件變量用來進行出入隊的同步。另外構造函數必須傳入隊列大小參數,所以為有界隊列,默認是Lock為非公平鎖。

  7. offer操作:在隊尾插入元素,如果隊列滿則返回false,否者入隊返回true。由於在操作共享變量前加了鎖【final ReentrantLock lock = this.lock; 獲取獨占鎖 lock.lock();】,所以不存在內存不可見問題,加過鎖后獲取的共享變量都是從主內存獲取的,而不是在CPU緩存或者寄存器里面的值,釋放鎖后修改的共享變量值會刷新會主內存中。另外這個隊列是使用循環數組實現,所以計算下一個元素存放下標時候有些特殊。【i=putIndex;  return(++i == items.length) ? 0 : i;】另外insert后調用 notEmpty.signal();是為了激活調用notEmpty.await()阻塞后放入notEmpty條件隊列中的線程。

  8. put操作:在隊列尾部添加元素,如果隊列滿則等待隊列有空位置插入后返回。【final ReentrantLock lock = this.lock;  獲取可被中斷鎖  lock.lockInterruptibly();】如果隊列滿了那么當前線程會阻塞,直到出隊操作調用了notFull.signal方法激活該線程。
  9. size操作:獲取隊列元素個數,非常精確,因為計算size時候加了獨占鎖,其他線程不能入隊或者出隊或者刪除元素
  10. ArrayBlockingQueue通過使用全局獨占鎖實現同時只能有一個線程進行入隊或者出隊操作,這個鎖的粒度比較大,有點類似在方法上添加synchronized的意味。其中offer,poll操作通過簡單的加鎖進行入隊出隊操作,而put,take則使用了條件變量實現如果隊列滿則等待,如果隊列空則等待,然后分別在出隊和入隊操作中發送信號激活等待線程實現同步。另外相比LinkedBlockingQueue,ArrayBlockingQueue的size操作的結果是精確的,因為計算前加了全局鎖。

8. LinkedBlockingQueue(JUC)

1. LinkedBlockingQueue 結構圖

 

 

一個由鏈接節點支持的可選有界隊列。

2. LinkedBlockingQueue 重要特點

  1. 一個基於已鏈接節點的、范圍任意的 blocking queue。此隊列按 FIFO(先進先出)排序元素。隊列的頭部 是在隊列中時間最長的元素。隊列的尾部 是在隊列中時間最短的元素。新元素插入到隊列的尾部,並且隊列獲取操作會獲得位於隊列頭部的元素。鏈接隊列的吞吐量通常要高於基於數組的隊列,但是在大多數並發應用程序中,其可預知的性能要低。

  2. 可選的容量范圍構造方法參數作為防止隊列過度擴展的一種方法。如果未指定容量,則它等於 Integer.MAX_VALUE除非插入節點會使隊列超出容量,否則每次插入后會動態地創建鏈接節點。

  3. LinkedBlockingQueue中也有兩個Node分別用來存放首尾節點,並且里面有個初始值為0的原子變量count用來記錄隊列元素個數,另外里面有兩個ReentrantLock的獨占鎖,分別用來控制元素入隊和出隊加鎖,其中takeLock用來控制同時只有一個線程可以從隊列獲取元素,其他線程必須等待,putLock控制同時只能有一個線程可以獲取鎖去添加元素,其他線程必須等待。另外notEmpty和notFull用來實現入隊和出隊的同步。 另外由於出入隊是兩個非公平獨占鎖,所以可以同時又一個線程入隊和一個線程出隊,其實這個是個生產者-消費者模型。

9. PriorityBlockingQueue(JUC)

1. PriorityBlockingQueue 結構圖

 

一個基於優先級堆的無界優先級阻塞隊列。

2. PriorityBlockingQueue 重要特點

  1. 一個基於優先級堆的無界阻塞隊列。,它使用與類 PriorityQueue 相同的順序規則,並且提供了阻塞獲取操作。雖然此隊列邏輯上是無界的,但是資源被耗盡時試圖執行 add 操作也將失敗(導致 OutOfMemoryError)。
  2. 此類不允許使用 null 元素。依賴自然順序的優先級隊列也不允許插入不可比較的對象(這樣做會導致拋出 ClassCastException)。
  3. 此類及其迭代器可以實現 Collection 和 Iterator 接口的所有可選 方法。iterator() 方法中提供的迭代器並 保證以特定的順序遍歷 PriorityBlockingQueue 的元素。如果需要有序地進行遍歷,則應考慮使用 Arrays.sort(pq.toArray())。此外,可以使用方法 drainTo 按優先級順序移除 全部或部分元素,並將它們放在另一個 collection 中。
  4. 在此類上進行的操作不保證具有同等優先級的元素的順序。如果需要實施某一排序,那么可以定義自定義類或者比較器,比較器可使用修改鍵斷開主優先級值之間的聯系。例如,以下是應用先進先出 (first-in-first-out) 規則斷開可比較元素之間聯系的一個類。要使用該類,則需要插入一個新的 FIFOEntry(anEntry) 來替換普通的條目對象。
  5. PriorityBlockingQueue內部有個數組queue用來存放隊列元素,size用來存放隊列元素個數,allocationSpinLockOffset是用來在擴容隊列時候做cas的,目的是保證只有一個線程可以進行擴容。
  6. 由於這是一個優先級隊列所以有個比較器comparator用來比較元素大小。lock獨占鎖對象用來控制同時只能有一個線程可以進行入隊出隊操作。notEmpty條件變量用來實現take方法阻塞模式。這里沒有notFull 條件變量是因為這里的put操作是非阻塞的,為啥要設計為非阻塞的是因為這是無界隊列。
  7. 最后PriorityQueue q用來搞序列化的。如下構造函數,默認隊列容量為11,默認比較器為null;

10. DelayQueue(JUC)

1. DelayQueue 結構圖

 

一個使用優先級隊列實現的無界阻塞隊列,只有在延遲期滿時才能從中提取元素。

DelayQueue隊列中每個元素都有個過期時間,並且隊列是個優先級隊列,當從隊列獲取元素時候,只有過期元素才會出隊列。

2. DelayQueue 重要特點

  1. Delayed 元素的一個無界阻塞隊列,只有在延遲期滿時才能從中提取元素。該隊列的頭部 是延遲期滿后保存時間最長的 Delayed 元素。如果延遲都還沒有期滿,則隊列沒有頭部,並且 poll 將返回 null

  2. 當一個元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一個小於等於 0 的值時,將發生到期。即使無法使用 take 或 poll 移除未到期的元素,也不會將這些元素作為正常元素對待。例如,size 方法同時返回到期和未到期元素的計數。

  3. 此隊列不允許使用 null 元素。

  4. DelayQueue中內部使用的是PriorityQueue存放數據,使用ReentrantLock實現線程同步,可知是阻塞隊列。另外隊列里面的元素要實現Delayed接口,一個是獲取當前剩余時間的接口,一個是元素比較的接口,因為這個是有優先級的隊列。

11. SychronousQueue(JUC)

1. SychronousQueue 結構圖

一個不存儲元素、沒有內部容量的阻塞同步隊列。

SynchronousQueue的吞吐量高於LinkedBlockingQueue 和 ArrayBlockingQueue。

2. SychronousQueue 重要特點

  1. 一個不存儲元素、沒有內部容量的阻塞隊列,其中每個插入操作必須等待另一個線程的對應移除操作 ,反之亦然。同步隊列沒有任何內部容量,甚至連一個隊列的容量都沒有。不能在同步隊列上進行 peek,因為僅在試圖要移除元素時,該元素才存在;除非另一個線程試圖移除某個元素,否則也不能(使用任何方法)插入元素;也不能迭代隊列,因為其中沒有元素可用於迭代。隊列的 是嘗試添加到隊列中的首個已排隊插入線程的元素;如果沒有這樣的已排隊線程,則沒有可用於移除的元素並且 poll() 將會返回 null。對於其他 Collection 方法(例如 contains),SynchronousQueue 作為一個空 collection。

  2. 此隊列不允許 null 元素

  3. 同步隊列類似於 CSP 和 Ada 中使用的 簡單聚集(rendezvous)機制信道。它非常適合於傳遞性設計,在這種設計中,在一個線程中運行的對象要將某些信息、事件或任務傳遞給在另一個線程中運行的對象,它就必須與該對象同步。 

  4. 對於正在等待的生產者和使用者線程而言,此類支持可選的公平排序策略。默認情況下不保證這種排序。但是,使用公平設置為 true 所構造的隊列可保證線程以 FIFO 的順序進行訪問。

  5. SynchronousQueue的吞吐量高於LinkedBlockingQueue 和 ArrayBlockingQueue。

12. LinkedTransferQueue(JUC)

1. LinkedTransferQueue 結構圖

LinkedTransferQueue是一個由鏈表結構組成的無界阻塞TransferQueue隊列。

2. LinkedTransferQueue 重要特點

  1. LinkedTransferQueue是一個由鏈表結構組成的無界阻塞TransferQueue隊列。
  2. 相對於其他阻塞隊列LinkedTransferQueue多了tryTransfer和transfer方法。
  3. transfer方法。如果當前有消費者正在等待接收元素(消費者使用take()方法或帶時間限制的poll()方法時),transfer方法可以把生產者傳入的元素立刻transfer(傳輸)給消費者。如果沒有消費者在等待接收元素,transfer方法會將元素存放在隊列的tail節點,並等到該元素被消費者消費了才返回。
  4. tryTransfer方法則是用來試探下生產者傳入的元素是否能直接傳給消費者。如果沒有消費者等待接收元素,則返回false。和transfer方法的區別是tryTransfer方法無論消費者是否接收,方法立即返回。而transfer方法是必須等到消費者消費了才返回。

  5.  對於帶有時間限制的tryTransfer(E e, long timeout, TimeUnit unit)方法,則是試圖把生產者傳入的元素直接傳給消費者,但是如果沒有消費者消費該元素則等待指定的時間再返回,如果超時還沒消費元素,則返回false,如果在超時時間內消費了元素,則返回true。

13. LinkedBlockingDeque(JUC)

1. LinkedBlockingDeque 結構圖

 

 一個基於已鏈接節點的、任選范圍的阻塞雙端隊列。

2. LinkedBlockingDeque 重要特點

  1. 一個基於已鏈接節點的、任選范圍的阻塞雙端隊列。
  2. 可選的容量范圍構造方法參數是一種防止過度膨脹的方式。如果未指定容量,那么容量將等於 Integer.MAX_VALUE只要插入元素不會使雙端隊列超出容量,每次插入后都將動態地創建鏈接節點。
  3. 大多數操作都以固定時間運行(不計阻塞消耗的時間)。異常包括 removeremoveFirstOccurrenceremoveLastOccurrencecontainsiterator.remove() 以及批量操作,它們均以線性時間運行。

 

摘錄網址

  1. 並發隊列-無界非阻塞隊列 ConcurrentLinkedQueue 原理探究
  2. 並發隊列-有界阻塞隊列ArrayBlockingQueue原理探究
  3. 並發隊列-無界阻塞隊列LinkedBlockingQueue原理探究
  4. 並發隊列-無界阻塞優先級隊列PriorityBlockingQueue原理探究
  5. JUC源碼分析-集合篇(八):SynchronousQueue


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM