# PriorityBlockingQueue

java并发 专栏收录该内容
4 篇文章 0 订阅

## 1.PriorityQueue

### 1.2PriorityQueue

  PriorityQueue<Integer> queue = new PriorityQueue<>();
System.out.println(queue);
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());

-25
-3
13
20

public class Student {
private String name;

private Integer score;
}

public static void main(String[] args) {
Comparator<Student> scoreComparator = new Comparator<Student>() {
public int compare(Student c1, Student c2) {
if (c1.getScore() > c2.getScore()) {
return -1;
} else if (c1.getScore() < c2.getScore()) {
return 1;
} else return 0;
}
};
PriorityQueue<Student> priorityQueue = new PriorityQueue<>(11, scoreComparator);

System.out.println(priorityQueue.poll());
System.out.println(priorityQueue.poll());
System.out.println(priorityQueue.poll());
System.out.println(priorityQueue.poll());

}

Student{name='B', score=100}
Student{name='A', score=99}
Student{name='D', score=98}
Student{name='C', score=89}

//构造方法中，如果不指定大小的话，默认大小为 11
private static final int DEFAULT_INITIAL_CAPACITY = 11;
//能扩容的最大值
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

//存放数据的数组
//the two children of queue[n] are queue[2*n+1] and queue[2*(n+1)].
transient Object[] queue;

//当前大小
private int size = 0;

// 大小比较器，如果不指定，按照自然序排序
private final Comparator<? super E> comparator;

//队列被改变的次数
transient int modCount = 0;

return offer(e);
}
public boolean offer(E e) {
if (e == null)  //不允许加入空值
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1);//扩容
size = i + 1;
if (i == 0)
queue[0] = e;
else
siftUp(i, e);//重新排序
return true;
}

private void grow(int minCapacity) {
int oldCapacity = queue.length;
// 如果节点个数小于 64，那么增加的 oldCap + 2 的容量
// 如果节点数大于等于 64，那么增加 oldCap 的一半
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
//设置最大值
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
queue = Arrays.copyOf(queue, newCapacity);
}

private void siftUp(int k, E x) {
if (comparator != null)
siftUpUsingComparator(k, x);
else
siftUpComparable(k, x);
}

@SuppressWarnings("unchecked")
private void siftUpComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>) x;
while (k > 0) {
int parent = (k - 1) >>> 1;//父节点位置
Object e = queue[parent];
if (key.compareTo((E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = key;
}

@SuppressWarnings("unchecked")
private void siftUpUsingComparator(int k, E x) {
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (comparator.compare(x, (E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = x;
}

public E poll() {
if (size == 0)
return null;
int s = --size;
modCount++;
E result = (E) queue[0];
E x = (E) queue[s];
queue[s] = null;
if (s != 0)
siftDown(0, x);
return result;
}

private void siftDown(int k, E x) {
if (comparator != null)
siftDownUsingComparator(k, x);
else
siftDownComparable(k, x);
}

@SuppressWarnings("unchecked")
private void siftDownComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>)x;
int half = size >>> 1;        // loop while a non-leaf
while (k < half) {
int child = (k << 1) + 1; // assume left child is least
Object c = queue[child];
int right = child + 1;
if (right < size &&
((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
c = queue[child = right];
if (key.compareTo((E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = key;
}

@SuppressWarnings("unchecked")
private void siftDownUsingComparator(int k, E x) {
int half = size >>> 1;
while (k < half) {
int child = (k << 1) + 1;
Object c = queue[child];
int right = child + 1;
if (right < size &&
comparator.compare((E) c, (E) queue[right]) > 0)
c = queue[child = right];
if (comparator.compare(x, (E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = x;
}

## 2.PriorityBlockingQueue

PriorityQueue 的线程安全版本，能自动扩容的无界队列.使用ReentrantLock+Condition控制.


//构造方法中，如果不指定大小的话，默认大小为 11
private static final int DEFAULT_INITIAL_CAPACITY = 11;

//存放数据的数组
//the two children of queue[n] are queue[2*n+1] and queue[2*(n+1)].
private transient Object[] queue;

//当前大小
private transient int size;

// 大小比较器，如果不指定，按照自然序排序
private transient Comparator<? super E> comparator;

// 并发控制所用的锁
private final ReentrantLock lock;

private final Condition notEmpty;

// 获取这个锁，才能进行扩容操作
private transient volatile int allocationSpinLock;
    public void put(E e) {
offer(e); // 无边队列，不会阻塞
}

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;
}

private void tryGrow(Object[] array, int oldCap) {
lock.unlock(); //释放独占锁，扩容操作和读操作可以同时进行，提高吞吐量。
Object[] newArray = null;
// CAS 操作，获取锁
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;
}
//如果 queue != array，说明在allocationSpinLock CAS之前，有其他线程给 queue 分配了其他的空间
if (newCap > oldCap && queue == array)
newArray = new Object[newCap];
} finally {
// 重置，也就是释放锁
allocationSpinLock = 0;
}
}
if (newArray == null) // 其他的线程也在做扩容的操作
lock.lock();// 重新获取锁
if (newArray != null && queue == array) {
queue = newArray;
System.arraycopy(array, 0, newArray, 0, oldCap);
}
}

• 0
点赞
• 0
评论
• 0
收藏
• 一键三连
• 扫一扫，分享海报

11-26 9644

09-02 85
05-05 9092
04-15 1182
12-01 6万+
10-04 260
01-12 1211
04-28 8963
03-18 2072