ArrayBlockingQueue源码解析

先说下 put 和 take 这2个 会让线程 处于watting状态的方法

arraybockingQueue 是基于 数组 和 读写指针
还有 condition 实现的 condition 是aqs的内部类
aqs 内部类中 Node 可以理解为 对象监视器monitor中的 entry set 入口集
而condition 可以理解为 wait set 等待集
不过 condition 是可以允许有多个的。
[Node 也是condition的实现 只不过是单向链表而 CLH 同步队列是 双向链表]

其中子所以有2个 条件等待 队列 是因为 在同步队列CLH队列上 等待唤醒的节点
有可能是 take 也有可能是put 如果 unlock 唤醒 nextNode.Thread 的话
有可能put满了 还是put的线程 那么 为了防止这样出现 所以
做一个where 判断 如果put满了 那么从 clh队列 加入 put condition 然后又 从
put condition 移到 clh 队列 等待唤醒

public void put(E e) throws InterruptedException {
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();// 获取独占式 非公平锁 默认 这个是可中断的
    						// 如果 唤醒之时不是 unpark唤醒的直接抛出异常
    try {
        while (count == items.length) // count 代表了 数组中 放入object 的个数
            notFull.await(); // 如果一直没有人消费 那么停止 生产 进入等待链表中等待 被唤醒
		// 被唤醒后 进入insert 如果上面被唤醒 count 不等于length 那么
		// 一定是可以 insert的
        enqueue(e);
    } finally {
        lock.unlock();
    }
}
private void enqueue(E x) {
	
    final Object[] items = this.items;
    //赋值   
    items[putIndex] = x;
  
    // 可以把 这个看成一个圆形 每put 一次 那么下次的 put指针就加一
    // 和 netty中的bytebuf中的读写指针 或者说和 nio中的 bytebuff 的positing 类似
    // 每次put后 item个数加1 然后唤醒 在take 等待的节点移动到clh队列中等待唤醒
    // put take 都是按顺序 的 所以只要拿到锁 count != 数组的长度 那么一定可以put成功
    if (++putIndex == items.length)
        putIndex = 0;
    count++;
    notEmpty.signal();
}
// 这几个方法都一样 没什么好说的了
public E take() throws InterruptedException {
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == 0)
            notEmpty.await();
        return dequeue();
    } finally {
        lock.unlock();
    }
}
private E dequeue() {
	// 取出来 然后 读take 指针 移动
    final Object[] items = this.items;

    E x = (E) items[takeIndex];
    items[takeIndex] = null;
    if (++takeIndex == items.length)
        takeIndex = 0;
    count--;
    if (itrs != null)
        itrs.elementDequeued();
    notFull.signal();
    return x;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值