学习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(); } }
根据对象寻找在数组中的下标位置