Summary:
- public class PriorityBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable
- 本类与普通的PriorityBlockingQueue类中的方法基本一致,区别在于本类的方法都会在方法执行前先加锁执行完再解锁;
- add、put会调用notEmpty.signal();唤醒等待的线程
- take如果遇到队列为空则;调用await()方法,阻塞知道被唤醒
Fields:
private final ReentrantLock lock; //锁
private final Condition notEmpty; //条件锁,用于队列为空时阻塞
private transient volatile int allocationSpinLock;
private transient Comparator<? super E> comparator; //比较器
private transient Object[] queue;
Constructor:
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];
}
put&add
//该方法会阻塞,添加成功返回true,否则爆出异常
//添加成功会触发notEmpty.signal();使得原本在读取数据时阻塞的线程能够解除阻塞
public void put(E e) {
offer(e);
}
public boolean add(E e) {
return offer(e);
}
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock(); //此处上锁,所以offer方法会产生阻塞
int n, cap;
Object[] array;
while ((n = size) >= (cap = (array = queue).length))
tryGrow(array, cap); //扩容,直到扩容成功才退出循环,注意这里扩容的工作并不一定是本线程完成的,具体原因看扩容方法tryGrow
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;
}
take
//从队列中读取一个数据,如果队列没有数据则阻塞
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
E result;
try {
while ( (result = dequeue()) == null)
notEmpty.await();
} finally {
lock.unlock();
}
return result;
}
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;
}
}
poll
//该方法只是尝试去从队列中获取第一个数,如果没有则返回null
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return dequeue();
} finally {
lock.unlock();
}
}
扩容操作;
该操作先释放锁;最后再尝试获取锁
然后很多线可能都来请求扩容,先进行CAS操作判断当前是否只有自己一个线程在扩容;
如果是则正常情况扩容;
不是则直到只有自己一个线程再去正常扩容;
正常库容还会判断自己是否是第一次在这里扩容,如果不是则不操作System.arraycopy()
private void tryGrow(Object[] array, int oldCap) {
lock.unlock(); //先释放锁
Object[] newArray = null;
if (allocationSpinLock == 0 &&
UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset, 0, 1)) {
try {
int newCap = oldCap + ((oldCap < 64) ?
(oldCap + 2) : // grow faster if small
(oldCap >> 1));
if (newCap - MAX_ARRAY_SIZE > 0) { // possible overflow
int minCap = oldCap + 1;
if (minCap < 0 || minCap > MAX_ARRAY_SIZE)
throw new OutOfMemoryError();
newCap = MAX_ARRAY_SIZE;
}
if (newCap > oldCap && queue == array)
newArray = new Object[newCap];
} finally {
allocationSpinLock = 0;
}
}
if (newArray == null) // back off if another thread is allocating
Thread.yield(); //如果有桶等级的线程在等待,可以叫它们先干活,当前线程休息下
lock.lock();
if (newArray != null && queue == array) {
queue = newArray;
System.arraycopy(array, 0, newArray, 0, oldCap);
}
}
UNSAFE
上面出现的UNSAFE是一种非阻塞同步机制;
大概意思就是先操作,如果达不到预期目的再操作一次,直到成功为止;
CAS操作;只有通过bootstrap ClassLoader加载的class才能访问它;
// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long allocationSpinLockOffset;
static {
try {
UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> k = PriorityBlockingQueue.class;
allocationSpinLockOffset = UNSAFE.objectFieldOffset
(k.getDeclaredField("allocationSpinLock"));
} catch (Exception e) {
throw new Error(e);
}
}