学习BlockingQueue之PriorityBlockingQueue实现原理 - warrior1234 - 博客园

一:概念

  PriorityBlockingQueue 是一个支持优先级的无界阻塞队列。默认情况下元素 采取自然顺序升序排列。也可以自定义类实现 compareTo()方法来指定元素排序 规则,

或者初始化 PriorityBlockingQueue 时,指定构造参数 Comparator 来对元素 进行排序。需要注意的是不能保证同优先级元素的顺序。

二:示例

main方法测试方法:

生产者线程:

消费者线程:

通过输出结果可以看出数据在对列里面已经排序,所以消费者线程消费的时候是有序的。

三:看一下PriorityBlockingQueue 这个类的源码

默认容量 11

数组最大分配值

 

 内部维护一个数组

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

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

 

看一下构造方法:

入参有初始容量、比较器

 还可以初始化一个容器

看一下offer和poll方法:

offer方法:

如果入参元素为null,则抛异常,  加锁,如果元素的数量等于数组的容量时,就要扩容;如果数组还有空间时,就会入队,

入队会判断是否初始化比较器,如果有比较器,则按照比较器就行排序,没有,则元素必须具有可比较性

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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方法:

上锁,然后调用出队方法:

?

1

2

3

4

5

6

7

8

9

public E poll() {

final ReentrantLock lock = this`.lock;`

lock.lock();

try {

return dequeue();

} finally {

lock.unlock();

}

}

如果对列为空,则返回null,如果不为空,则把第一个元素返回,然后重新排序

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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:根据索引删除元素

?

1

2

3

4

5

6

7

8

9

10

11

12

13

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();

}

}

根据对象寻找在数组中的下标位置


原网址: 访问
创建于: 2021-09-10 13:44:55
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论