注意:本文内容基于JDK11,不同版本会有差异
数据结构
queue本质上的数据结构还是一个数组。items就是queue中用来存放数据的数组。
源码解析
本文以put/add/offer三个加入元素的方法为入口,来解析ArrayBlockingQueue的底层逻辑。
代码中的enqueuq是元素的入列的具体实现。它本质上的逻辑就是往数组中添加元素
/**
* 在当前放置位置插入元素,前进和信号。仅在持有锁时调用。
* @param e
*/
private void enqueue(E e){
final Object[] items = this.items;
items[putIndex] = e;
if(++putIndex == items.length){
putIndex = 0;
}
count++;
notEmpty.signal();
}
put方法
put方法会在队列已满的情况下进入线程阻塞。它的高并发是通过可重入锁ReentrantLock来保证线程安全的。
/**
* put方法会被阻塞
* @param e
* @throws InterruptedException
*/
public void put(E e) throws InterruptedException {
//判断e是不是空,如果是则返回空指针异常
Objects.requireNonNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
//如果队列已满,那么put方法进入阻塞
while (count == items.length){
notFull.await();
}
enqueue(e);
}finally {
lock.unlock();
}
}
add方法
add方法通过调用父类的add方法。在父类中,add方法则是通过调用对应的offer方法来进行实现的。所以add的最终实现方法还是offer。add方法和offer方法的区别在于如果队列满了,add方法会抛出异常,而offer方法只返回true或者false。
@Override
public boolean add(E e) {
return super.add(e);
}
offer方法
/**
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null and
* this queue does not permit null elements
* @throws IllegalArgumentException if some property of this element
* prevents it from being added to this queue
*/
@Override
public boolean offer(E e) {
Objects.requireNonNull(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
if(count == items.length){
return false;
}else{
enqueue(e);
return true;
}
}finally {
lock.unlock();
}
}