天天看點

Java之集合(二十二)PriorityBlockingQueue

  轉載請注明源出處:http://www.cnblogs.com/lighten/p/7510799.html

1.前言

  本章介紹阻塞隊列PriorityBlockingQueue。這是一個無界有序的阻塞隊列,排序規則和之前介紹的PriorityQueue一緻,隻是增加了阻塞操作。同樣的該隊列不支援插入null元素,同時不支援插入非comparable的對象。它的疊代器并不保證隊列保持任何特定的順序,如果想要順序周遊,考慮使用Arrays.sort(pq.toArray())。該類不保證同等優先級的元素順序,如果你想要強制順序,就需要考慮自定義順序或者是Comparator使用第二個比較屬性。

2.PriorityBlockingQueue

2.1 資料結構

Java之集合(二十二)PriorityBlockingQueue

  DEFAULT_INITIAL_CAPACITY:預設隊列容量11

  MAX_ARRAY_SIZE:最大可配置設定隊列容量Integer.MAX_VALUE - 8,減8是因為有的VM實作在數組頭有些内容

  queue:隊列元素數組。平衡二叉堆實作,父節點下标是n,左節點則是2n+1,右節點是2n+2。最小的元素在最前面

  size:目前隊列中元素的個數

  comparator:決定隊列中元素先後順序的比較器

  lock:所有public方法的鎖

  notEmpty:隊列為空時的阻塞條件

  allocationSpinLock:擴容數組配置設定資源時的自旋鎖,CAS需要

  q:PriorityQueue隻用于序列化的時候,為了相容之前的版本。隻有在序列化和反序列化的時候不為null。

2.2 基本操作

   放入一個元素:

Java之集合(二十二)PriorityBlockingQueue

  和PriorityQueue的實作基本一緻差別就是在于加鎖了,并發出了非空信号喚醒阻塞的擷取線程。具體操作原理看:PriorityQueue。這裡值得一說的就是tryGrow的實作,其用了一個while循環來處理,下面是具體實作。

Java之集合(二十二)PriorityBlockingQueue

  其先放開了鎖,然後通過CAS設定allocationSpinLock來判斷哪個線程獲得了擴容權限,如果沒搶到權限就會讓出CPU使用權。最後還是要鎖住開始真正的擴容。擴容權限争取到了就是計算大小,配置設定數組。暫不肯定為什麼這麼麻煩要配置設定數組的時候釋放鎖,暫猜測這樣做效率會更高。

  其它的操作過程都和PriorityQueue的類似,不再進行介紹。