并发编程-ArrayBlockingQueue源码分析
1、ArrayBlockingQueue成员变量维护了take下标,put下标,元素数量,一个ReentrantLock锁,notEmpty条件,notFull条件
public class ArrayBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, Serializable { //数组,存储元素 final Object[] items; //取元素下标 int takeIndex; //放元素下标 int putIndex; //元素数量 int count; //使用一个锁,实现 1、put数据到队列时,take数据的线程进入等待队列,阻塞并挂起,2、take数据时,put数据的线程进入等待队列,阻塞并挂起 final ReentrantLock lock; //条件队列 private final Condition notEmpty; //条件队列 private final Condition notFull; // transient ArrayBlockingQueue<E>.Itrs itrs; }
2、阻塞队列put数据操作逻辑
a、put请求到到达后,先调用lock.lockInterruptibly()方法加锁
b、判断当前队列是否已满
- 满了,则调用notFull.await释放锁,当前线程进入阻塞状态,等待唤醒获取锁
- 不满,执行入队逻辑(元素放入到数组下标为puIndex的内存位置,putIndex下标加1,并判断putIndex下标是否等于队列长度,等于则设置putIndex为0,最后调用notEmpty.sigal()方法唤醒阻塞的take线程去抢占锁,注意此时的锁还未释放)
c、调用lock.unlock()释放锁
public void put(E var1) throws InterruptedException { //检查数据是否为空,为空抛出异常 checkNotNull(var1); ReentrantLock var2 = this.lock; //加锁 var2.lockInterruptibly(); try { //##循环的作用:当阻塞的线程被唤醒后,再次进行循环条件判断队列是否已满,不满就跳出循环执行后续逻辑## while(this.count == this.items.length) { //1、队列满了,调用Condition.await()方法释放锁,线程挂起(进入WAIT无时限等待状态),等待唤醒(唤醒后进入阻塞状态获取锁,再进入就绪状态) this.notFull.await(); } //2、队列不满,执行入队 this.enqueue(var1); } finally { //2.1、入队完成之后,释放锁 var2.unlock(); } } private void enqueue(E var1) { Object[] var2 = this.items; //1、把元素放入到数组的putIndex下标位置 var2[this.putIndex] = var1; //2、putIndex下标加1,并判断putIndex是否等于数组长度,等于则设置putIndex为0 if (++this.putIndex == var2.length) { this.putIndex = 0; } //3、数组元素加1 ++this.count; //4、通过condition.sigal()唤醒等待的take线程去抢占锁,注意此时只是唤醒,但是锁还未被释放 this.notEmpty.signal(); }
3、阻塞队列take数据逻辑
a、take数据请求到达后,调用lock.lockInterruptibly()方法加锁
b、循环队列是否为空
- 为空,则调用Condition.await()方法释放锁,线程进入阻塞状态,等待获取锁
- 不为空,则执行出队逻辑(取出数组下标为takeIndex的元素,takeIndex加1,判断takeIndex是否等于数组长度,等于则设置takeIndex为0,最后调用Condition.sigal()方法唤醒put数据的阻塞线程准备抢占锁,注意此时锁还未释放)
c、调用lock.unlock()方法释放锁
public E take() throws InterruptedException { ReentrantLock var1 = this.lock; //加锁 var1.lockInterruptibly(); Object var2; try { //##循环的作用:当阻塞的线程被唤醒后,会再次进入循环判断队列是否为空,不为空跳出循环执行后续逻辑## while(this.count == 0) { //1、为空则调用await()方法,take线程释放锁并挂起(进入WAIT无时限等待状态),等待唤醒(唤醒后进入阻塞状态获取锁,再进入就绪状态) this.notEmpty.await(); } //调用出队逻辑 var2 = this.dequeue(); } finally { //释放锁 var1.unlock(); } return var2; } private E dequeue() { Object[] var1 = this.items; //根据takeIndex下标获取队列中的数据 Object var2 = var1[this.takeIndex]; //取出后takeIndex下标位置数据置空 var1[this.takeIndex] = null; //takeIndex加1,并判断takeIndex跟队列长度是否相等 if (++this.takeIndex == var1.length) { //相等则takeIndex置为0 this.takeIndex = 0; } //队列元素数量减1 --this.count; // if (this.itrs != null) { // this.itrs.elementDequeued(); } //调用notFull.sigal()方法,通知唤醒put阻塞线程,准备获取锁,注意此时take线程还没释放锁 this.notFull.signal(); return var2; }

浙公网安备 33010602011771号