写点什么

ArrayBlockingQueue 源码分析 - 构造方法

作者:zarmnosaj
  • 2022 年 7 月 09 日
  • 本文字数:1320 字

    阅读完需:约 4 分钟

特点

ArrayBlockingQueue 也叫做数组阻塞队列,底层使用的是数组。


  1. 有界的阻塞数组,容量一旦创建,后续大小无法修改

  2. 元素是有顺序的,按照先入先出进行排序,从队尾插入数据数据,从队头拿数据

  3. 队列满时,往队列中 put 数据会被阻塞,队列空时,往队列中拿数据也会被阻塞

源码属性

public class ArrayBlockingQueue<E> extends AbstractQueue<E>        implements BlockingQueue<E>, java.io.Serializable {        ...                final Object[] items;                int takeIndex;                int putIndex;                int count;                final ReentrantLock lock;                private final Condition notEmpty;                private final Condition notFull;        ...
}
复制代码


final Object[] items; 队列存放在 object 的数组里面,数组大小必须在初始化的时候手动设置,没有默认大小


int takeIndex; 下次拿数据的时候的索引位置


int putIndex;下次放数据的索引位置


int count; 当前已有元素的大小


final ReentrantLock lock; 可重入的锁


private final Condition notEmpty; take 的队列


private final Condition notFull; put 的队列


其中 takeIndex 和 putIndex,分别表示下次拿数据和下次放数据的索引,所以在新增数据和拿取数据时都无需进行多余的计算,可以直接知道应该新增到什么位置、从什么位置拿数据。

构造方法

public ArrayBlockingQueue(int capacity, boolean fair) {    if (capacity <= 0)        throw new IllegalArgumentException();    this.items = new Object[capacity];    lock = new ReentrantLock(fair);    // 队列不为空 Condition,在 put 成功时使用    notEmpty = lock.newCondition();    // 队列不满 Condition,在 take 成功时使用    notFull =  lock.newCondition();}
复制代码


notEmpty = lock.newCondition();队列不为空 Condition,在 put 成功时使用


notFull = lock.newCondition();队列不满 Condition,在 take 成功时使用


其中 fair 参数主要用于设置读写锁是否公平。


有指定初始数据的构造方法:


    public ArrayBlockingQueue(int capacity, boolean fair,                              Collection<? extends E> c) {        this(capacity, fair);
final ReentrantLock lock = this.lock; lock.lock(); // Lock only for visibility, not mutual exclusion try { int i = 0; try { for (E e : c) { checkNotNull(e); items[i++] = e; } } catch (ArrayIndexOutOfBoundsException ex) { throw new IllegalArgumentException(); } count = i; putIndex = (i == capacity) ? 0 : i; } finally { lock.unlock(); } }
复制代码


int i = 0; 表示插入的位置


for (E e : c) { checkNotNull(e); items[i++] = e; } 如果 c 的大小超过了数组的大小会抛出异常


putIndex = (i == capacity) ? 0 : i; 如果插入的位置是队尾,则下次从 0 开始插入

发布于: 刚刚阅读数: 4
用户头像

zarmnosaj

关注

靡不有初,鲜克有终 2020.02.06 加入

成都后端混子

评论

发布
暂无评论
ArrayBlockingQueue源码分析-构造方法_7月月更_zarmnosaj_InfoQ写作社区