PriorityBlockingQueue類也是實現阻塞隊列的一種工具類,同Array BlockingQueue類和LinkedBlockingQueue一樣,最爲消息中間件的實現類。同步線程之間的消息。
如果要分析PriorityBlockingQueue就必須要看看PriorityQueue是如何實現的了。類PriorityQueue和類PriorityBlockingQueue都是用Object [ ] queue來實現隊列中的元素的存
放,這一點和ArrayBlockingQueue類一樣。而且阻塞隊列類PriorityBlockingQueue的入列和出列操作都是使用一把同步鎖,但是LinkedBlockingQueue類的入列和出列操作都是自己使用獨立的一把鎖。
PriorityBlockingQueue類還有一個與前兩種阻塞隊列類不同的地方是:PriorityBlockingQueue對數組queue存放的元素的排列順序進行了管理,數組queue的第一個元素是最小的元素,因此每次取出來的元素都是最下的元素。queue數組滿足在二叉樹結構下,所有的子二叉樹的根節點是在該樹下的最小值。
簡而言之,在二叉樹結構下,數組元素在樹的根節點到葉子節點路徑中的所有節點的值都是有序排列的。
圖:
PriorityBlockingQueue類的屬性
//存放隊列元素的數組
private transient Object[] queue;
//隊列中元素的個數
private transient int size;
//維護數組排序的時候進行比較的比較子
private transient Comparator<? super E> comparator;
//獲取隊列資源的同步鎖
private final ReentrantLock lock;
//鎖獲取條件
private final Condition notEmpty;
PriorityBlockingQueue類使用的一些方法:
PriorityBlockingQueue類實際上就是比PriorityQueue類多了同步的功能。許多的入列算法和出列算法都是一樣的,下面就只給出PriorityQueue類的函數,而
PriorityBlockingQueue類似方法讀者自己進行分析,對比一下就會很簡單了,你自己也會同時掌握兩個類的使用。
PriorityQueue類出列操作
//隊列出列是獲取並刪除在數組的第一個元素位置,並將最後一個元素放在根節點位置,這個影響的只是二叉樹的一條路徑,然後對這條路徑進行半冒泡修復
public E poll() {
if (size == 0)
return null;
int s = --size;
modCount++;
E result = (E) queue[0];
E x = (E) queue[s];
queue[s] = null;
if (s != 0)
siftDown(0, x);
return result;
}
PriorityBlockingQueue類出列操作
/**
* Mechanics for poll(). Call only while holding lock.
*/
private E extract() {
E result;
int n = size - 1;
if (n < 0)
result = null;
else {
Object[] array = queue;
result = (E) array[0];
E x = (E) array[n];
array[n] = null;
Comparator<? super E> cmp = comparator;
if (cmp == null)
siftDownComparable(0, x, array, n);
else
siftDownUsingComparator(0, x, array, n, cmp);
size = n;
}
return result;
}
PriorityQueue類的入列操作 public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)//如果隊列長度超容量,就增容
grow(i + 1);
size = i + 1;
if (i == 0)//隊列爲空時,直接插入隊列
queue[0] = e;
else //如果隊列中已經存在元素了,則插入元素後要維護隊列的排序(變異堆排序)
siftUp(i, e);
return true;
}
PriorityQueue類的出列操作 public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
E result;
try {
while ( (result = extract()) == null)
notEmpty.await();
} finally {
lock.unlock();
}
return result;
}
對於這些隊列的API就不做過多解釋了,如果讀者有興趣可以去了解更多Priority BlockingQueue類和PriorityQueue類的算法和數據結構以及思想都是一樣的,下一章我將把PriorityQueue類的所有源碼的註釋分析發表出來,大家有興趣可以閱
讀下,註釋是我對PriorityQueue類的理解。