线程安全的阻塞队列,用来处理 生产者-消费者 问题。
当队列容器满时,生产者线程被阻塞直到队列未满。
当队列容器为空时,消费者线程阻塞直到队列非空。
主要介绍BlockingQueue下三个实现类
1。ArrayBlockingQueue
底层使用数组来实现的有界阻塞队列。
一旦构造方法确定了数组容量大小后就不能改变,使用可重入锁来控制,
构造方法中可以选择实现公平锁还是非公平锁。
公平锁的意思是先等待的线程最先访问到ArrayBlockingQueue。
默认是非公平锁,因为公平锁会降低队列的吞吐性能。
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
不管是插入操作还是读取操作,都要获取到锁才能操作。
/** Main lock guarding all access */
final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;
2。LinkedBlockingQueue
底层使用单向链表实现的无界阻塞队列。
默认容量大小为Integer.MAX_VALUE
一般需要指定容量大小,不然会消耗大量内存。
指定容量大小可以当做有界阻塞队列来使用
不指定大小则当做意义上的无界阻塞队列。
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
3。PriorityBlockingQueue
一个支持优先级的无界阻塞队列
默认情况下按照自然顺序对元素进行排序
底层使用数组来实现,默认初始为11大小的数组,
后面随着元素增加会不断扩容。
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];
}
添加元素时判断是否当前元素个数已经大于数组容量了,就进行扩容
while ((n = size) >= (cap = (array = queue).length))
tryGrow(array, cap);
新的容量是看旧容量的多少来具体分配的,
旧容量越小增长的快一点(增长(oldCap + 2) ),
旧容量大一点的旧增长的慢一点(增长(oldCap >> 1))
int newCap = oldCap + ((oldCap < 64) ?
(oldCap + 2) : // grow faster if small
(oldCap >> 1));
网友评论