小白系列-----ArrayBlockingQueue

ArrayBlockingQueue

  • 基于数组实现了阻塞队列
  • 必须指定空间大小,可以设置生产、消费线程等待顺序的公平性、默认非公平
  • 使用公平获取资源将会降低吞吐量,但是可以避免饥饿
基本属性&方法:
/** The queued items */
final Object[] items;

/** items index for next take, poll, peek or remove */
int takeIndex;

/** items index for next put, offer, or add */
int putIndex;

/** Number of elements in the queue */
int count;

/*
     * Concurrency control uses the classic two-condition algorithm
     * found in any textbook.
     */
/** 访问数据时的锁 */
final ReentrantLock lock;

/** Condition for waiting takes */
// 正在等待拿数据的条件队列
private final Condition notEmpty;

/** Condition for waiting puts */
// 正在等待添加数据的条件队列
private final Condition notFull;

// 使用迭代器时的共享状态
transient Itrs itrs = null;

// 索引-1 后的下标
final int dec(int i) {
    return ((i == 0) ? items.length : i) - 1;
}
// 返回某个位置的元素
final E itemAt(int i) {
    return (E) items[i];
}
offer()
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();
    }
}

private void enqueue(E x) {
    // assert lock.getHoldCount() == 1;
    // assert items[putIndex] == null;
    // 使用final不可变,防止意外修改, 提升效率
    final Object[] items = this.items;
    items[putIndex] = x;
    // 更新putIndex的值
    if (++putIndex == items.length)
        putIndex = 0;
    count++;
    // 唤醒准备添加数据的线程
    notEmpty.signal();
}
poll
public E poll() {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        // 弹出元素
        return (count == 0) ? null : dequeue();
    } finally {
        lock.unlock();
    }
}

private E dequeue() {
    // assert lock.getHoldCount() == 1;
    // assert items[takeIndex] != null;
    final Object[] items = this.items;
    @SuppressWarnings("unchecked")
    E x = (E) items[takeIndex];
    // 将takeIndex位置的元素弹出,并置空
    items[takeIndex] = null;
    if (++takeIndex == items.length)
        takeIndex = 0;
    count--;
    if (itrs != null)
        itrs.elementDequeued();
    // 唤醒需要添加元素的线程
    notFull.signal();
    return x;
}
remove()
public boolean remove(Object o) {
    if (o == null) return false;
    final Object[] items = this.items;
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        if (count > 0) {
            final int putIndex = this.putIndex;
            int i = takeIndex;
            // 从takeIndex开始寻找是否有待删除的元素存在
            do {
                if (o.equals(items[i])) {
                    // 删除i位置的元素,同时需要将i-putIndex之间的元素前移
                    removeAt(i);
                    return true;
                }
                if (++i == items.length)
                    i = 0;
            } while (i != putIndex);
        }
        // 没有找到待删除元素
        return false;
    } finally {
        lock.unlock();
    }
}

void removeAt(final int removeIndex) {
    // assert lock.getHoldCount() == 1;
    // assert items[removeIndex] != null;
    // assert removeIndex >= 0 && removeIndex < items.length;
    final Object[] items = this.items;
    // 如果待删除元素刚好就是takeInde对应的元素
    if (removeIndex == takeIndex) {
        // removing front item; just advance
        items[takeIndex] = null;
        if (++takeIndex == items.length)
            takeIndex = 0;
        count--;
        if (itrs != null)
            itrs.elementDequeued();
    } else {
        // an "interior" remove

        // slide over all others up through putIndex.
        final int putIndex = this.putIndex;
        // 将putIndex前的元素都前移
        for (int i = removeIndex;;) {
            int next = i + 1;
            if (next == items.length)
                next = 0;
            if (next != putIndex) {
                items[i] = items[next];
                i = next;
            } else {
                // 将putIndex前一个位置设置(此时为i)为null
                items[i] = null;
                this.putIndex = i;
                break;
            }
        }
        count--;
        if (itrs != null)
            itrs.removedAt(removeIndex);
    }
    // 唤醒等待添加元素的线程
    notFull.signal();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值