源码角度了解阻塞队列之ArrayBlockingQueue
Posted 周杰伦本人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了源码角度了解阻塞队列之ArrayBlockingQueue相关的知识,希望对你有一定的参考价值。
源码角度了解阻塞队列之ArrayBlockingQueue
关于阻塞队列的文章,之前的文章也有所介绍,今天从源码的角度再分析分析,接口是BlockingQueue,它的实现类很多,
ArrayBlockingQueue数组实现的环形队列,它定义了队头指针的队尾指针,一个ReentrantLock锁和两个Condition
put()方法
它的put方法:
public void put(E e) throws InterruptedException
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try
while (count == items.length)
notFull.await();
enqueue(e);
finally
lock.unlock();
put()方法中在此队列的尾部插入指定元素,如果队列已满,则阻塞等待队列可用。lock.lockInterruptibly()是可中断的锁,当其他线程中断该线程的时候,当前线程获取锁失败,这里调用了enqueue()方法:
enqueue()方法
private void enqueue(E x)
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
插入元素到当前队列中,这个方法是在获取到锁之后才能被调用的
- 放入元素
- 判断索引位置是否已经到队列尾部了,如果是,索引位置回到队头
- 通知其他线程
take()方法
逻辑和put()方法总体上差不多,判断count是否为0,如果为0,阻塞等待,否则调用dequeue()方法,dequeue()方法的逻辑又和enqueue()方法差不多
dequeue()方法
插入元素到当前队列中,这个方法是在获取到锁之后才能被调用的
- 获取索引元素
- 判断索引位置是否已经到队列尾部了,如果是,索引位置回到队头
- count减一
- 唤醒满足notFull条件上的线程
总结
这篇文章从ArrayBlockingQueue的put()方法和take()方法进行分析,ArrayBlockingQueue底层是使用数组实现的,它的这两个方法主要是对数组的操作,但是数组有固定长度,从它的构造方法中也能看出来必须要传入一个容量的参数,它的核心成员变量有count用来记录数组中元素个数,两个指针分别指向放入元素和取出元素的位置,两个Condition表示非空和非满,唤醒线程,实现线程间的交互
以上是关于源码角度了解阻塞队列之ArrayBlockingQueue的主要内容,如果未能解决你的问题,请参考以下文章
JDK源码那些事儿之ConcurrentLinkedQueue