源码角度了解阻塞队列之ArrayBlockingQueue

举报
周杰伦本人 发表于 2022/09/29 23:41:30 2022/09/29
【摘要】 源码角度了解阻塞队列之ArrayBlockingQueue put()方法 enqueue()方法 take()方法 dequeue()方法 总结 源码角度了解阻塞队列之ArrayBlockingQueue关于阻塞队列的文章,之前的文章也有所介绍,今天从源码的角度再分析分析,接口是BlockingQueue,它的实现类很多,ArrayBlockingQueue数组实现的环形队列,它定义了队...

源码角度了解阻塞队列之ArrayBlockingQueue

关于阻塞队列的文章,之前的文章也有所介绍,今天从源码的角度再分析分析,接口是BlockingQueue,它的实现类很多,

ArrayBlockingQueue数组实现的环形队列,它定义了队头指针的队尾指针,一个ReentrantLock锁和两个Condition

put()方法

它的put方法:

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();
        }
    }

put()方法中在此队列的尾部插入指定元素,如果队列已满,则阻塞等待队列可用。lock.lockInterruptibly()是可中断的锁,当其他线程中断该线程的时候,当前线程获取锁失败,这里调用了enqueue()方法:

enqueue()方法

 private void enqueue(E x) {
        final Object[] items = this.items;
        items[putIndex] = x;
        if (++putIndex == items.length)
            putIndex = 0;
        count++;
        notEmpty.signal();
    }

插入元素到当前队列中,这个方法是在获取到锁之后才能被调用的

  1. 放入元素
  2. 判断索引位置是否已经到队列尾部了,如果是,索引位置回到队头
  3. 通知其他线程

take()方法

逻辑和put()方法总体上差不多,判断count是否为0,如果为0,阻塞等待,否则调用dequeue()方法,dequeue()方法的逻辑又和enqueue()方法差不多

dequeue()方法

插入元素到当前队列中,这个方法是在获取到锁之后才能被调用的

  1. 获取索引元素
  2. 判断索引位置是否已经到队列尾部了,如果是,索引位置回到队头
  3. count减一
  4. 唤醒满足notFull条件上的线程

总结

这篇文章从ArrayBlockingQueue的put()方法和take()方法进行分析,ArrayBlockingQueue底层是使用数组实现的,它的这两个方法主要是对数组的操作,但是数组有固定长度,从它的构造方法中也能看出来必须要传入一个容量的参数,它的核心成员变量有count用来记录数组中元素个数,两个指针分别指向放入元素和取出元素的位置,两个Condition表示非空和非满,唤醒线程,实现线程间的交互

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。