ArrayBlockingQueue - 源码分析

前言

ArrayBlockingQueue(阻塞队列的一种) 的本质是一个有界数组,队列中元素遵循先进先出的规则。 这种队列是一种典型的有界缓冲区,一旦建立,他的长度就不能再改变。数组


队列的特色

  1. 先进先出。
  2. 当队列中的元素个数等于队列的长度时, 再往里面添加元素会形成阻塞,直到队列中的元素减小。
  3. 当队列中的元素个数等于 0 时,从队列中取出元素时,会形成阻塞, 直到队列中有新的元素。

几个重要属性

final Object[] items;// 队列容器

 int count;// 队列中的元素真实个数

 final ReentrantLock lock;// 主锁,控制全部的访问

 int takeIndex; /**  下一个要取出的元素索引*/

 int putIndex;/** 下一个要存放的索引*/

 private final Condition notEmpty; /**  标记队列是不是空*/

 private final Condition notFull; /**  至关于一个标志位, 标记队列是否存满*/

两个方法

添加元素的方法this

// 添加元素
  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);// 存入队列 并 唤醒 notEmpty 锁
        } finally {
            lock.unlock();
        }
  }

 // 非空校验
 private static void checkNotNull(Object v) {
        if (v == null)
            throw new NullPointerException();
 }

 // 入队
 private void enqueue(E x) {
        final Object[] items = this.items;
        items[putIndex] = x;
        if (++putIndex == items.length)// 若是队列满了
            putIndex = 0;// 从头开始放
        count++;
        notEmpty.signal();//唤醒
 }

取出元素的方法code

// 取出元素
 public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();// 队列中元素个数为0,等待
            return dequeue();// 返回队列中的元素
        } finally {
            lock.unlock();
        }
 }

 // 出队
 private E dequeue() {
        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;
 }

总结

本文只是简单介绍了 ArrayBlockingQueue 中最简单 且 最经常使用的方法,它自己其实还有不少实用的方法,好比预防超时之类的,之后会继续分享。索引

相关文章
相关标签/搜索