学习BlockingQueue之PriorityBlockingQueue实现原理
一:概念
PriorityBlockingQueue 是一个支持优先级的无界阻塞队列。默认情况下元素 采取自然顺序升序排列。也可以自定义类实现 compareTo()方法来指定元素排序 规则,
或者初始化 PriorityBlockingQueue 时,指定构造参数 Comparator 来对元素 进行排序。需要注意的是不能保证同优先级元素的顺序。
二:示例
main方法测试方法:

生产者线程:

消费者线程:


通过输出结果可以看出数据在对列里面已经排序,所以消费者线程消费的时候是有序的。
三:看一下PriorityBlockingQueue 这个类的源码
默认容量 11

数组最大分配值

内部维护一个数组

比较器,可以不初始化,但是对象必须具有比较性

只有一把锁,锁所有的public操作

看一下构造方法:
入参有初始容量、比较器

还可以初始化一个容器

看一下offer和poll方法:
offer方法:
如果入参元素为null,则抛异常, 加锁,如果元素的数量等于数组的容量时,就要扩容;如果数组还有空间时,就会入队,
入队会判断是否初始化比较器,如果有比较器,则按照比较器就行排序,没有,则元素必须具有可比较性
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock();
int n, cap;
Object[] array;
while ((n = size) >= (cap = (array = queue).length))
tryGrow(array, cap);
try {
Comparator<? super E> cmp = comparator;
if (cmp == null)
siftUpComparable(n, e, array);
else
siftUpUsingComparator(n, e, array, cmp);
size = n + 1;
notEmpty.signal();
} finally {
lock.unlock();
}
return true;
}
看一下扩容方法tryGrow


poll方法:
上锁,然后调用出队方法:
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return dequeue();
} finally {
lock.unlock();
}
}
如果对列为空,则返回null,如果不为空,则把第一个元素返回,然后重新排序
private E dequeue() {
int n = size - 1;
if (n < 0)
return null;
else {
Object[] array = queue;
E 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;
}
}
add和remove方法:
add方法的实现就是使用offer的逻辑

remove方法:
1:加锁 2:根据对象找到在数组中的索引 3:根据索引删除元素
public boolean remove(Object o) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
int i = indexOf(o);
if (i == -1)
return false;
removeAt(i);
return true;
} finally {
lock.unlock();
}
}
根据对象寻找在数组中的下标位置



浙公网安备 33010602011771号