PriorityBlockingQueue
特点:
1、可以指定内部元素的排序规则(即出队规则),即实现该接口的对象:java.util.Comparator<T>;
2、内部数据结构是对象数据组,Object[] queue;
3、默认长度:11,最大长度:Integer.MAX_VALUE - 8;
4、不支持放入空值,会抛异常:NullPointerException
5、放入元素有要求,二选一:
A、元素对象不用实现:java.lang.Comparable<T>,但是需要在构造参数中指定比较器:java.util.Comparator<T>
B、元素对象实现:java.lang.Comparable<T>,构造无需指定比较器:java.util.Comparator<T>
必须二选一,否则会抛异常,如果两个条件都满足了,那么默认会优先按指定的比较器来比较排序;
构造:
//1、无惨构造,使用默认长度11,不指定比较器,要求元素必须实现Comparable接口
public PriorityBlockingQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
//2、指定容量的构造,不指定比较器
public PriorityBlockingQueue(int initialCapacity) {
this(initialCapacity, null);
}
//3、指定容量和比较器的构造,元素顺序按照比较器指定的比较规则来
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];
}
//4、通过指定集合构造队列
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();
}
方法:
其方法和ArrayBlockingQueue和LinkedBlockingQueue类似,入队:add、offer、put;出队:remove、poll、take
其要注意的是:
1、入队时,元素会按照构造队列时指定的Comparator对象排序,或者,按照元素自身实现Comparable接口后的比较规则排序;
2、如果两种都满足,默认构造参数指定的Comparator有限;
应用场景:
1、放入队列的元素需要按照指定的规则排序出队,比如:带有不同优先级的任务,VIP客户的任务需要插队先处理;
使用示例:
import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
/**
* PriorityQueue <br>
* 特点:<br>
* 可以定义排序规则(即出队规则)的阻塞队列(针对已经在队列内的元素)<br>
* 数据结构:对象数组 <br>
* 默认长度11 <br>
* 不能放入空值 <br>
* 放入元素有要求,二选一:
* 1、元素对象不用实现:java.lang.Comparable<T>,但是需要在构造参数中指定比较器:java.util.Comparator<T>
* 2、元素对象实现:java.lang.Comparable<T>,构造无需指定比较器:java.util.Comparator<T>
* 必须二选一,否则会抛异常,如果两个条件都满足了,那么默认会优先按指定的比较器来比较排序;
*
*/
public class PriorityBlockingQueueTest {
private PriorityBlockingQueue<CustTask> priorityBlockingQueue = new PriorityBlockingQueue<CustTask>(10,
new Comparator<CustTask>() {
public int compare(CustTask o1, CustTask o2) {
return o1.getPriority() - o2.getPriority();// 优先级小的靠前排
}
});
//注意:采用这种不指定比较器的构造,要求放入的元素必须实现Comparable接口,否则会抛异常;
private PriorityBlockingQueue<CustTask> priorityBlockingQueue2 = new PriorityBlockingQueue<CustTask>();
public PriorityBlockingQueueTest() {
}
class CustTask {
private String name;
private int priority;
public CustTask(String name, int priority) {
this.name = name;
this.priority = priority;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
@Override
public String toString() {
return "name:" + this.getName() + " , priority:" + this.getPriority();
}
}
private void test() {
for (int i = 0; i < 10; i++) {
priorityBlockingQueue.offer(new CustTask("name" + i, 20 - i));
}
CustTask custTask = null;
while (true) {
custTask = priorityBlockingQueue.poll();// 为null表示没有元素了,不阻塞
if (null != custTask) {
System.out.println(custTask.toString());
} else {
break;
}
}
System.out.println("over");
}
public static void main(String[] args) {
new PriorityBlockingQueueTest().test();
}
}