前言
在jdk提供的队列中,有阻塞队列和非阻塞队列
阻塞队列是指:在添加元素的时候,如果队列已经满了,此时会阻塞当前入队的线程,将入队的线程放入到AQS的同步条件队列中,在队列元素出队之后,会尝试唤醒阻塞的线程,阻塞的线程将从条件队列进入到同步等待队列中进行排队;
在出队的时候,也是同样的道理,如果队列中元素为空,就会阻塞出队元素,进入到同步条件队列中,在队列中入队了元素之后,会唤醒阻塞的线程,阻塞的出队线程,从条件队列进入到等待队列中。进行排队,等待获取执行权限
非阻塞队列:在juc中,提供的非阻塞队列,是通过CAS来实现的,也就是说,如果在入队的时候,如果入队失败,会进行CAS自旋。而不是阻塞,进入到条件队列
除了阻塞和非阻塞队列之外,jdk还提供了优先级队里、延迟队列
阻塞队列
阻塞队列中,我比较熟悉的是ArrayBlockingQueue和LinkedBlockingQueue,所以,以这两个为例,来做一个学习
ArrayBlockingQueue
ArrayBlockingQueue,从名字就可以看出来,内部是数组结构,是有界的,那阻塞是怎么实现的呢?
在ArrayBlockingQueue中,维护了一个ReentrantLock和两个condition
/** Main lock guarding all access */
final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;
入队的源码
/**
* 这是入队的操作
* 1.加锁
* 2.判断当前数组中的元素个数等于数组长度,就返回false,表示此时队列已经满了
* 3.入队,入队成功的话,返回true
* 4.解锁
*/
public boolean offer(E e) {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count == items.length)
return false;
else {
enqueue(e);
return true;
}
} finally {
lock.unlock();
}
}
出队的源码
/**
* 这是出队的逻辑
* 1.首先加锁
* 2.如果当前队列中为空,就阻塞,调用condition的await()方法,将当前线程放入到同步条件队列中进行休眠
* 3.如果不为空,正常出队,所谓的出队,就是从数组头部出队,返回对应的元素
* 4.然后释放锁
* @return
* @throws InterruptedException
*/
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue()