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类的理解。