聊聊BlockingQueue(实现篇)

 

下图是BlockingQueue接口的主要实现

 

我们先看第一个ArrayBlockingQueue

主要属性

/** 存放队列元素的数组 */
final Object[] items;

/** 出队列的当前索引值 */
int takeIndex;

/** 入队列的下一个索引值 */
int putIndex;

/** 队列大小 */
int count;

/** 队列操作锁 */
final ReentrantLock lock;

/** 出队列Condition */
private final Condition notEmpty;

/** 入队列Condition */
private final Condition notFull;

/**
 * 队列活动共享状态
 *
 */
transient Itrs itrs = null;

下面我们看两个主要方法

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();//释放锁
    }
}

这里重点分析下aqs中Condition的应用
 

public E take() throws InterruptedException {
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();//可中断获取锁
    try {
        while (count == 0)
            notEmpty.await();//非空等待
        return dequeue();//出队列
    } finally {
        lock.unlock();//释放锁
    }
}

上面看到在队列已满或者队列为空,分别对应notFull,notEmpty等待,并且加入了等待队列,那么从哪里唤醒的呢

private void enqueue(E x) {
    final Object[] items = this.items;//获取元素的数组
    items[putIndex] = x;//新元素加入数组
    if (++putIndex == items.length)
        putIndex = 0;
    count++;//大小加1
    notEmpty.signal();//唤醒因队列为空阻塞的线程
}
dequeue()方法类似,不再啰嗦。
private E dequeue() {
    final Object[] items = this.items;
    @SuppressWarnings("unchecked")
    E x = (E) items[takeIndex];//获取出队列元素
    items[takeIndex] = null;//置空
    if (++takeIndex == items.length)//已经取到最后一个,归零
        takeIndex = 0;
    count--;//大小减1
    if (itrs != null)
        itrs.elementDequeued();//归零,清除弱引用
    notFull.signal();//唤醒因队列满等待的线程
    return x;
}

这里就是为什么使用的await(),signal()方法,而不是使用wait和notify,notifyAll呢,留给大家解答吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值