简介
PriorityBlockingQueue是一个支持优先级的无界阻塞队列。默认情况下元素采用自然顺序升序排列。也可以自定义类实现compareTo()方法来指定元素排序规则,或者初始化PriorityBlockingQueue时,指定构造参数Comparator来对元素进行排序。但需要注意的是不能保证同优先级元素的顺序。
和ArrayBlockingQueue一样内部使用数组实现,插入和获取数据使用同一把锁。不同的是,不管有无指定长度,都会实现可以实现自动扩容;在构造函数需传入comparator,用于插入元素时继续排序,若没有传入comparator,则插入的元素必须实现Comparatable接口。
构造方法
public PriorityBlockingQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
public PriorityBlockingQueue(int initialCapacity) {
this(initialCapacity, null);
}
public PriorityBlockingQueue(int initialCapacity,
Comparator<? super E> comparator) {
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.lock = new ReentrantLock();
this.notEmpty = lock.newCondition();
this.comparator = comparator;
this.queue = new Object[initialCapacity];
}
public PriorityBlockingQueue(Collection<? extends E> c) {
this.lock = new ReentrantLock();
this.notEmpty = lock.newCondition();
boolean heapify = true; // true if not known to be in heap order
boolean screen = true; // true if must screen for nulls
if (c instanceof SortedSet<?>) {
SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
this.comparator = (Comparator<? super E>) ss.comparator();
heapify = false;
}
else if (c instanceof PriorityBlockingQueue<?>) {
PriorityBlockingQueue<? extends E> pq =
(PriorityBlockingQueue<? extends E>) c;
this.comparator = (Comparator<? super E>) pq.comparator();
screen = false;
if (pq.getClass() == PriorityBlockingQueue.class) // exact match
heapify = false;
}
Object[] a = c.toArray();
int n = a.length;
// If c.toArray incorrectly doesn't return Object[], copy it.
if (a.getClass() != Object[].class)
a = Arrays.copyOf(a, n, Object[].class);
if (screen && (n == 1 || this.comparator != null)) {
for (int i = 0; i < n; ++i)
if (a[i] == null)
throw new NullPointerException();
}
this.queue = a;
this.size = n;
if (heapify)
heapify();
}
定义实体类
public class Human {
private int maney;
private String name;
public Human(int maney, String name){
this.maney = maney;
this.name = name;
}
public int getManey() {
return maney;
}
public String getName() {
return name;
}
@Override
public String toString() {
return getName() + "[存款:"+getManey()+"]";
}
}
重写比较器
public class HumanComparator implements Comparator<Human> {
@Override
public int compare(Human o1, Human o2) {
return o2.getManey() - o1.getManey();
}
}
生产线程
public class ProducerRunnable implements Runnable{
private static final String name = "明刚红李刘吕赵黄王孙朱曾游丽吴昊周郑秦丘";
private Random random = new Random();
private PriorityBlockingQueue<Human> queue;
public ProducerRunnable(PriorityBlockingQueue<Human> queue) {
this.queue = queue;
}
@Override
public void run() {
for(int i = 0; i < 20; i ++){
Human human = new Human(random.nextInt(10000), "小" + name.charAt(i));
queue.put(human);
System.out.println(human + " 开始排队...");
}
}
}
消费线程
public class ConsumerRunnable implements Runnable{
private PriorityBlockingQueue<Human> queue;
public ConsumerRunnable(PriorityBlockingQueue<Human> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true){
Human take = queue.poll();
if (take == null){
break;
}
System.out.println(take + " 办理业务.");
}
}
}
测试类
public class TestMain {
public static void main(String[] args) throws InterruptedException {
PriorityBlockingQueue<Human> queue = new PriorityBlockingQueue<>(200, new HumanComparator());
Thread thread = new Thread(new ProducerRunnable(queue));
thread.start();
thread.join();
new Thread(new ConsumerRunnable(queue)).start();
}
}
测试结果:
小明[存款:9296] 开始排队...
小刚[存款:765] 开始排队...
小红[存款:333] 开始排队...
小李[存款:3912] 开始排队...
小刘[存款:5732] 开始排队...
小吕[存款:3714] 开始排队...
小赵[存款:8439] 开始排队...
小黄[存款:7330] 开始排队...
小王[存款:9535] 开始排队...
小孙[存款:1421] 开始排队...
小朱[存款:8308] 开始排队...
小曾[存款:5211] 开始排队...
小游[存款:8264] 开始排队...
小丽[存款:8383] 开始排队...
小吴[存款:7664] 开始排队...
小昊[存款:2715] 开始排队...
小周[存款:9760] 开始排队...
小郑[存款:8158] 开始排队...
小秦[存款:869] 开始排队...
小丘[存款:1806] 开始排队...
小周[存款:9760] 办理业务.
小王[存款:9535] 办理业务.
小明[存款:9296] 办理业务.
小赵[存款:8439] 办理业务.
小丽[存款:8383] 办理业务.
小朱[存款:8308] 办理业务.
小游[存款:8264] 办理业务.
小郑[存款:8158] 办理业务.
小吴[存款:7664] 办理业务.
小黄[存款:7330] 办理业务.
小刘[存款:5732] 办理业务.
小曾[存款:5211] 办理业务.
小李[存款:3912] 办理业务.
小吕[存款:3714] 办理业务.
小昊[存款:2715] 办理业务.
小丘[存款:1806] 办理业务.
小孙[存款:1421] 办理业务.
小秦[存款:869] 办理业务.
小刚[存款:765] 办理业务.
小红[存款:333] 办理业务.
常用方法
入队
public boolean add(E e) {
return offer(e);
}
public boolean offer(E e) {
// 若插入的元素为null,则直接抛出NullPointerException异常
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;
}
出队
public E poll() {
// 获取全局锁
final ReentrantLock lock = this.lock;
lock.lock();
try {
return dequeue();
} finally {
// 释放全局锁
lock.unlock();
}
}