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

Posted 周杰伦本人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了源码角度了解阻塞队列之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表示非空和非满,唤醒线程,实现线程间的交互

以上是关于源码角度了解阻塞队列之ArrayBlockingQueue的主要内容,如果未能解决你的问题,请参考以下文章

JDK源码那些事儿之ConcurrentLinkedQueue

JDK源码那些事儿之LinkedTransferQueue

JDK源码那些事儿之ConcurrentLinkedDeque

阻塞队列之ArrayBlockingQueue源码分析

阻塞队列之ArrayBlockingQueue源码分析

JAVA并发之阻塞队列浅析