面试题答案
一键面试PriorityBlockingQueue的稳定性说明
- PriorityBlockingQueue概述:PriorityBlockingQueue是Java集合框架中的一个无界阻塞队列,它根据元素的自然顺序(如果元素实现了Comparable接口)或者根据构造时提供的Comparator进行排序。
- 稳定性分析:PriorityBlockingQueue并不保证排序的稳定性。稳定性是指如果两个元素具有相同的排序键,它们在排序后的顺序与插入顺序一致。在PriorityBlockingQueue中,当多个元素优先级相同时,并不会维护插入顺序。
多线程插入相同优先级元素的处理
- 源码分析:当向PriorityBlockingQueue插入元素时,主要方法是
offer(E e)
和put(E e)
(put
方法内部调用offer
)。
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) {
@SuppressWarnings("unchecked")
E x = (E) array[n];
if (x == null || e.compareTo(x) < 0)
siftUpComparable(n, e, array);
else
siftUpUsingComparator(n, e, array, cmp);
}
size = n + 1;
notEmpty.signal();
} finally {
lock.unlock();
}
return true;
}
这里在插入元素时,使用siftUpComparable
或siftUpUsingComparator
方法将新元素放置到合适位置。以siftUpComparable
为例:
private static <T> void siftUpComparable(int k, T x, Object[] array) {
Comparable<? super T> key = (Comparable<? super T>)x;
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = array[parent];
if (key.compareTo((T) e) >= 0)
break;
array[k] = e;
k = parent;
}
array[k] = key;
}
这个过程只是保证元素按优先级顺序排列,并没有记录插入顺序。所以当多个线程同时插入相同优先级元素时,它们在队列中的顺序是未定义的,取决于线程竞争和内部堆调整的实际情况。
总结来说,PriorityBlockingQueue不保证排序稳定性,多个线程插入相同优先级元素时,其在队列中的先后顺序是不确定的。