Java8 ArrayBlockingQueue 源码解析

    目录

1、定义

2、构造方法

3、add / offer / put 

4、poll / take / peek

5、remove / clear /drainTo

6、iterator / Itr / Itrs 

7、doSomeSweeping  /  register

8、queueIsEmpty / elementDequeued / takeIndexWrapped / removedAt

9、next / hasNext / remove


      ArrayBlockingQueue表示一个基于数组实现的固定容量的,先进先出的,线程安全的队列(栈),本篇博客就详细讲解该类的实现细节。

1、定义

    ArrayBlockingQueue的类继承关系如下:

Java8 ArrayBlockingQueue 源码解析_第1张图片

其核心接口BlockingQueue包含的方法定义如下:

Java8 ArrayBlockingQueue 源码解析_第2张图片

上图中的Queue和Collection下面都有两个接口,这两个接口是BlockingQueue覆写的,并不是说这两类只有这两接口,Collection和Queue的主要接口实现都由AbstractQueue实现了,我们重点关注上图中列出来的这些接口的实现。

ArrayBlockingQueue包含的属性如下:

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

    /** items index for next take, poll, peek or remove */
    int takeIndex;

    /** offer,add,put等方法将元素保存到该索引处 */
    int putIndex;

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

    /** 互斥锁*/
    final ReentrantLock lock;

    /** 如果数组是空的,在该Condition上等待 */
    private final Condition notEmpty;

    /** 如果数组是满的,在该Condition上等待 */
    private final Condition notFull;

    /** 遍历器实现 */
    transient Itrs itrs = null;

 重点关注以下方法的实现。

2、构造方法

public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }

//capacity表示队列的容量,fair表示是否使用公平锁
public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
        this.items = new Object[capacity];
        lock = new ReentrantLock(fair);
        notEmpty = lock.newCondition();
        notFull =  lock.newCondition();
    }

public ArrayBlockingQueue(int capacity, boolean fair,
                              Collection c) {
        this(capacity, fair);

        final ReentrantLock lock = this.lock;
        //加锁的目的是为了其他CPU能够立即看到修改
        //加锁和解锁底层都是CAS,会强制修改写回主存,对其他CPU可见
        lock.lock(); // Lock only for visibility, not mutual exclusion
        try {
            int i = 0;
            try {
                for (E e : c) {
                    checkNotNull(e);
                    items[i++] = e;
                }
            } catch (ArrayIndexOutOfBoundsException ex) {
                throw new IllegalArgumentException();
            }
            count = i;
            putIndex = (i == capacity) ? 0 : i;
        } finally {
            lock.unlock();
        }
    }

3、add / offer / put 

     这三个方法都是往队列中添加元素,说明如下:

  • add方法依赖于offer方法,如果队列满了则抛出异常,否则添加成功返回true;
  • offer方法有两个重载版本,只有一个参数的版本,如果队列满了就返回false,否则加入到队列中,返回true,add方法就是调用此版本的offer方法;另一个带时间参数的版本,如果队列满了则等待,可指定等待的时间,如果这期间中断了则抛出异常,如果等待超时了则返回false,否则加入到队列中返回true;
  • put方法跟带时间参数的offer方法逻辑一样,不过没有等待的时间限制,会一直等待直到队列有空余位置了,再插入到队列中,返回true
public boolean add(E e) {
        //调用子类offer方法实现,如果队列满了则抛出异常
        return super.add(e);
    }

public boolean offer(E e) {
        //非空检测
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            //数组满了
            if (count == items.length)
                return false;
            else {
                enqueue(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }

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方法,只不过可以指定等待的时间
public boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException {

        checkNotNull(e);
        long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            //数组满了则等待
            while (count == items.length) {
                if (nanos <= 0)
                    return false;
                nanos = notFull.awaitNanos(nanos);
            }
            enqueue(e);
            return true;
        } finally {
            lock.unlock();
        }
    }

public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }


 private void enqueue(E x) {
        final Object[] items = this.items;
        //保存到putIndex索引处
        items[putIndex] = x;
        //数组满了,将其重置为0
        if (++putIndex == items.length)
            putIndex = 0;
        //数组元素个数增加    
        count++;
        //唤醒因为队列是空的而等待的线程
        notEmpty.signal();
    }

private static void checkNotNull(Object v) {
        if (v == null)
            throw new NullPointerException();
    }

4、poll / take / peek

     这几个方法都是获取队列顶的元素,具体说明如下:

  • poll方法有两个重载版本,第一个版本,如果队列是空的,返回null,否则移除并返回队列头部元素;另一个带时间参数的版本,如果栈为空则等待,可以指定等待的时间,如果等待超时了则返回null,如果被中断了则抛出异常,否则移除并返回栈顶元素
  • take方法同带时间参数的poll方法,但是不能指定等待时间,会一直等待直到队列中有元素为止,然后移除并返回栈顶元素
  • peek方法只是返回队列头部元素,不移除
public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            //如果为空,返回null,否则取出一个元素
            return (count == 0) ? null : dequeue();
        } finally {
            lock.unlock();
        }
    }

    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            //如果空的,则等待
            while (count == 0)
                notEmpty.await();
            //取出一个元素   
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0) {
                if (nanos <= 0)
                    return null; //等待超时,返回null
                //数组为空,等待    
                nanos = notEmpty.awaitNanos(nanos);
            }
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

    public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            //返回栈顶元素,takeIndex值不变
            return itemAt(takeIndex); // null when queue is empty
        } finally {
            lock.unlock();
        }
    }

private E dequeue() {
        // assert lock.getHoldCount() == 1;
        // assert items[takeIndex] != null;
        final Object[] items = this.items;
        @SuppressWarnings("unchecked")
        //取出takeIndex的元素,将其置为null
        E x = (E) items[takeIndex];
        items[takeIndex] = null;
        if (++takeIndex == items.length)
            takeIndex = 0;//取完了,从头开始取
        count--;
        if (itrs != null)
            //通知itrs栈顶的元素被移除了
            itrs.elementDequeued();
        //唤醒因为栈满了等待的线程    
        notFull.signal();
        return x;
    }

  final E itemAt(int i) {
        return (E) items[i];
    }

5、remove / clear /drainTo

      这三个方法用于从队列中移除元素,具体说明如下:

  • remove方法用于移除某个元素,如果栈为空或者没有找到该元素则返回false,否则从栈中移除该元素;移除时,如果该元素位于栈顶则直接移除,如果位于栈中间,则需要将该元素后面的其他元素往前面挪动,移除后需要唤醒因为栈满了而阻塞的线程
  • clear方法用于整个栈,同时将takeIndex置为putIndex,保证栈中的元素先进先出;最后会唤醒最多count个线程,因为正常一个线程插入一个元素,如果唤醒超过count个线程,可能导致部分线程因为栈满了又再次被阻塞
  • drainTo方法有两个重载版本,一个是不带个数,将所有的元素都移除并拷贝到指定的集合中;一个带个数,将指定个数的元素移除并拷贝到指定的集合中,两者的底层实现都是同一个方法。移除后需要重置takeIndex和count,并唤醒最多移除个数的因为栈满而阻塞的线程。
public boolean remove(Object o) {
        if (o == null) return false;
        final Object[] items = this.items;
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count > 0) {
                final int putIndex = this.putIndex;
                int i = takeIndex;
                //从takeIndex开始往后遍历直到等于putIndex
                do {
                    if (o.equals(items[i])) {
                        //找到目标元素,将其移除
                        removeAt(i);
                        return true;
                    }
                    //走到数组末尾了又从头开始,put时也按照这个规则来
                    if (++i == items.length) 
                        i = 0;
                } while (i != putIndex);
            }
            //如果数组为空,返回false
            return false;
        } finally {
            lock.unlock();
        }
    }


public void clear() {
        final Object[] items = this.items;
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            int k = count;
            if (k > 0) {
                final int putIndex = this.putIndex;
                int i = takeIndex;
                //从takeIndex开始遍历直到i等于putIndex,将数组元素置为null
                do {
                    items[i] = null;
                    if (++i == items.length)
                        i = 0;
                } while (i != putIndex);
                //注意此处没有将这两个index置为0,只是让他们相等,因为只要相等就可以实现栈先进先出了
                takeIndex = putIndex;
                count = 0;
                if (itrs != null)
                    itrs.queueIsEmpty();
                //如果有因为栈满了而等待的线程,则将其唤醒
                //注意这里没有使用signalAll而是通过for循环来signal多次,单纯从唤醒线程来看是可以使用signalAll的,效果跟这里的for循环是一样的
                //如果有等待的线程,说明count就是当前线程的最大容量了,这里清空了,最多只能put count次,一个线程只能put 1次,只唤醒最多count个线程就避免了
                //线程被唤醒后再次因为栈满了而阻塞   
                for (; k > 0 && lock.hasWaiters(notFull); k--)
                    notFull.signal();
            }
        } finally {
            lock.unlock();
        }
    }

public int drainTo(Collection c) {
        return drainTo(c, Integer.MAX_VALUE);
    }

public int drainTo(Collection c, int maxElements) {
        //校验参数合法
        checkNotNull(c);
        if (c == this)
            throw new IllegalArgumentException();
        if (maxElements <= 0)
            return 0;
        final Object[] items = this.items;
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            //取两者之间的最小值
            int n = Math.min(maxElements, count);
            int take = takeIndex;
            int i = 0;
            try {
                //从takeIndex开始遍历,取出元素然后添加到c中,直到满足个数要求为止
                while (i < n) {
                    @SuppressWarnings("unchecked")
                    E x = (E) items[take];
                    c.add(x);
                    items[take] = null;
                    if (++take == items.length)
                        take = 0;
                    i++;
                }
                return n;
            } finally {
                // Restore invariants even if c.add() threw
                if (i > 0) {
                    //取完了,修改count减去i
                    count -= i;
                    takeIndex = take;
                    if (itrs != null) {
                        if (count == 0)
                             //通知itrs 栈空了
                            itrs.queueIsEmpty();
                        else if (i > take)
                             //说明take中间变成0了,通知itrs
                            itrs.takeIndexWrapped();
                    }
                    //唤醒在因为栈满而等待的线程,最多唤醒i个,同上避免线程被唤醒了因为栈又满了而阻塞
                    for (; i > 0 && lock.hasWaiters(notFull); i--)
                        notFull.signal();
                }
            }
        } finally {
            lock.unlock();
        }
    }

void removeAt(final int removeIndex) {
        final Object[] items = this.items;
        if (removeIndex == takeIndex) {
            //如果移除的就是栈顶的元素
            items[takeIndex] = null;
            if (++takeIndex == items.length)
                takeIndex = 0;
            //元素个数减1    
            count--;
            if (itrs != null)
                itrs.elementDequeued();
        } else {
            //如果移除的是栈中间的某个元素,需要将该元素后面的元素往前挪动
            final int putIndex = this.putIndex;
            for (int i = removeIndex;;) {
                int next = i + 1;
                //到数组末尾了,从头开始
                if (next == items.length)
                    next = 0;
                if (next != putIndex) {
                    //将后面一个元素复制到前面来
                    items[i] = items[next];
                    i = next;
                } else {
                    //如果下一个元素的索引等于putIndex,说明i就是栈中最后一个元素了,直接将该元素置为null
                    items[i] = null;
                    //重置putIndex为i
                    this.putIndex = i;
                    break;
                }
            }
            count--;
            if (itrs != null)
                //通知itrs节点移除了
                itrs.removedAt(removeIndex);
        }
        //唤醒因为栈满了而等待的线程
        notFull.signal();
    }

6、iterator / Itr / Itrs 

     iterator方法返回一个迭代器实例,用于实现for循环遍历和部分Collection接口,该方法的实现如下:

public Iterator iterator() {
        return new Itr();
    }

Itr() {
            // assert lock.getHoldCount() == 0;
            lastRet = NONE;
            final ReentrantLock lock = ArrayBlockingQueue.this.lock;
            lock.lock();
            try {
                if (count == 0) {
                    //NONE和DETACHED都是常量
                    cursor = NONE;
                    nextIndex = NONE;
                    prevTakeIndex = DETACHED;
                } else {
                    //初始化各属性
                    final int takeIndex = ArrayBlockingQueue.this.takeIndex;
                    prevTakeIndex = takeIndex;
                    nextItem = itemAt(nextIndex = takeIndex);
                    cursor = incCursor(takeIndex);
                    if (itrs == null) {
                        //初始化Itrs,将当前线程注册到Itrs
                        itrs = new Itrs(this);
                    } else {
                        //将当前线程注册到Itrs中,并执行清理
                        itrs.register(this); // in this order
                        itrs.doSomeSweeping(false);
                    }
                    prevCycles = itrs.cycles;
                }
            } finally {
                lock.unlock();
            }
        }

Itrs(Itr initial) {
    register(initial);
}

//根据index计算cursor
 private int incCursor(int index) {
            // assert lock.getHoldCount() == 1;
            if (++index == items.length)
                index = 0;
            if (index == putIndex)
                index = NONE;
            return index;
        }

void register(Itr itr) {
    head = new Node(itr, head);
}

  Itr和Itrs都是ArrayBlockingQueue的两个内部类,Itr包含的属性如下:

 /** 查找下一个nextItem的索引,如果是NONE表示到栈底了*/
 private int cursor; 

 /** 下一次调用next()方法返回的元素,初始值为takeIndex对应的元素 */
 private E nextItem; 

 /**nextItem元素对应的索引,如果是NONE表示nextItem是null, 如果是REMOVED表示nextItem被移除了,初始值就等于takeIndex*/
 private int nextIndex; 

 /**上一次被返回的元素,如果*/
 private E lastItem; 

 /**lastItem对应的索引 */
 private int lastRet; 

 /**Itr初始化时takeIndex的值 */
 private int prevTakeIndex; 

 /**Itr初始化时iters.cycles的值 */
 private int prevCycles; 

 /** 特殊的索引值,表示这个索引对应的元素不存在 */
 private static final int NONE = -1; 

 /** 特殊的索引值,表示该索引对应的元素已经被移除了 */
 private static final int REMOVED = -2; 

 /** 特殊的prevTakeIndex值,表示当前Iter已经从Iters中解除关联了 */
 private static final int DETACHED = -3;

  Itrs包含的属性如下: 

  /**当takeIndex变成0以后加1 */
  int cycles = 0;

  /** Iter实例链表的链表头 */
  private Node head;

  /** Used to expunge stale iterators */
  private Node sweeper = null;

  private static final int SHORT_SWEEP_PROBES = 4;
  private static final int LONG_SWEEP_PROBES = 16;

 其中Node为Itrs的一个内部类,其定义如下:

Java8 ArrayBlockingQueue 源码解析_第3张图片

注意Node继承自WeakReference。 

7、doSomeSweeping  /  register

       Itrs内部维护了一个Itr实例链表,register方法用于将一个新的Itr实例加入到链表头,doSomeSweeping方法用于清除该链表中无效的Itr实例,查找这类实例是通过for循环实现的,初始for循环的次数是通过参数tryHandler控制的,如果为true,则循环16次,如果为false,则循环4次,在循环的过程中找到了一个无效的Itr实例,则需要再遍历16次,直到所有节点都遍历完成。注意这里的无效指的这个Itr实例已经同Itrs datached了,当ArrayBlockingQueue执行Itrs的回调方法时就不会处理这种Itr实例了,即Itr实例无法感知到ArrayBlockingQueue的改变了,这时基于Itr实例遍历的结果可能就不准确了。

//创建一个新的Itr实例时,会调用此方法将该实例添加到Node链表中
void register(Itr itr) {
            //创建一个新节点将其插入到head节点的前面
            head = new Node(itr, head);
        }

//用于清理那些陈旧的Node
void doSomeSweeping(boolean tryHarder) {
            // assert lock.getHoldCount() == 1;
            // assert head != null;
            //probes表示循环查找的次数
            int probes = tryHarder ? LONG_SWEEP_PROBES : SHORT_SWEEP_PROBES;
            Node o, p;
            final Node sweeper = this.sweeper;
            boolean passedGo;   // to limit search to one full sweep
            
            //o表示上一个有效节点,p表示当前遍历的节点,如果o为空,则p是head,否则是o的下一个节点
            //进入此方法,sweeper可能为null,head不会为null
            if (sweeper == null) {
                o = null;
                p = head;
                passedGo = true;
            } else {
                o = sweeper;
                p = o.next;
                passedGo = false;
            }

            for (; probes > 0; probes--) {
                if (p == null) {
                    if (passedGo)
                        break; //sweeper为null时,passedGo为true,终止循环,将sweeper赋值
                    //passedGo为false,sweeper不为null,因为p为null,还是将其置为true,即只能循环一次   
                    o = null;
                    p = head;
                    passedGo = true;
                }
                //获取关联的Itr
                final Itr it = p.get();
                final Node next = p.next;
                if (it == null || it.isDetached()) {
                    //如果it为null或者已经解除关联了
                    //只要找到了一个无效节点,则需要再遍历LONG_SWEEP_PROBES次,直到所有节点遍历完为止
                    probes = LONG_SWEEP_PROBES; // "try harder"
                    //将关联的Itr置为null
                    p.clear();
                    p.next = null;
                    if (o == null) { //sweeper为null或者sweeper的next为null时
                        //没有找到有效节点,重置head,将next之前的节点都移除
                        head = next;
                        if (next == null) {
                            //next为null,没有待处理的节点了,所以Itr都退出了,将itrs置为null
                            itrs = null;
                            return;
                        }
                    }
                    else
                        //将next作为o的下一个节点,即将p移除了
                        o.next = next;
                } else {
                    //p对应的Itr实例是有效的,将o置为p
                    o = p;
                }
                //处理下一个节点
                p = next;
            }
            //重置sweeper,p等于null说明节点都遍历完了,sweeper为null
            //如果p不等于null,说明还有未遍历的节点,将sweeper置为0,下一次遍历时可以重新从该节点开始遍历
            this.sweeper = (p == null) ? null : o;
        }

boolean isDetached() {
            // assert lock.getHoldCount() == 1;
            return prevTakeIndex < 0;
        }

 8、queueIsEmpty / elementDequeued / takeIndexWrapped / removedAt

      这四个方法都是在某种条件下,由ArrayBlockingQueue回调Itrs的方法,具体如下:

  • queueIsEmpty方法用于因为元素移除栈空了时调用的,会将Itr链表中的所有元素对Itr实例的引用置为null,将Itr实例的各属性置为null或者特殊index值
  • takeIndexWrapped方法用于takeIndex变成0了后调用,会增加cycles计数,如果当前cycles属性减去Itr实例的prevCycles属性大于1,则说明Itr初始化时栈中的元素都被移除了,此时再遍历无意义,将这类节点从Itr实例链表中移除,将对Itr的引用置为null,将Itr实例的各属性置为null或者特殊index值
  • removedAt方法用于从栈中注意不是栈顶移除元素时调用的,会重新计算cursor,lastRet,nextIndex等属性,如果计算出来的属性小于0,则将这个节点从Itr实例链表中移除,将Itr实例的各属性置为null或者特殊index值
  • elementDequeued方法时元素从栈顶移除时调用,如果当前栈空了则调用queueIsEmpty方法,如果takeIndex变成0了,则调用takeIndexWrapped方法
//从栈顶移除一个元素时回调的
void elementDequeued() {
            // assert lock.getHoldCount() == 1;
            if (count == 0)
                //如果栈空了
                queueIsEmpty();
            else if (takeIndex == 0)
                takeIndexWrapped();
        }

//栈变成空的以后回调此方法
void queueIsEmpty() {
            // assert lock.getHoldCount() == 1;
            //遍历链表
            for (Node p = head; p != null; p = p.next) {
                Itr it = p.get();
                if (it != null) {
                    //将引用清除
                    p.clear();
                    //通知Itr队列空了,将各参数置为null或者特殊index值
                    it.shutdown();
                }
            }
            //重置为null
            head = null;
            itrs = null;
        }

//当takeIndex变成0的时候回调的
void takeIndexWrapped() {
            // assert lock.getHoldCount() == 1;
            cycles++;
            //遍历链表,o表示上一个有效节点,p表示当前遍历的节点
            for (Node o = null, p = head; p != null;) {
                final Itr it = p.get();
                final Node next = p.next;
                if (it == null || it.takeIndexWrapped()) {
                    p.clear();
                    p.next = null;
                    if (o == null)
                        //之前的节点是无效节点,重置head,把next之前的节点都移除了
                        head = next;
                    else
                        //移除p这一个节点
                        o.next = next;
                } else {
                    //保存上一个有效节点
                    o = p;
                }
                //处理下一个节点
                p = next;
            }
            //没有有效节点,itrs置为null
            if (head == null)   // no more iterators to track
                itrs = null;
        }

//栈中某个元素被移除时调用
void removedAt(int removedIndex) {
            //遍历链表
            for (Node o = null, p = head; p != null;) {
                final Itr it = p.get();
                final Node next = p.next;
                //removedAt方法判断这个节点是否被移除了
                if (it == null || it.removedAt(removedIndex)) {
                    //将p从链表中移除
                    p.clear();
                    p.next = null;
                    if (o == null)
                        head = next;
                    else
                        o.next = next;
                } else {
                    //记录上一个有效节点
                    o = p;
                }
                //处理下一个有效节点
                p = next;
            }
            //无有效节点
            if (head == null)   // no more iterators to track
                itrs = null;
        }

//判断Itr这个节点是否应该被移除
boolean takeIndexWrapped() {
            // assert lock.getHoldCount() == 1;
            if (isDetached())
                return true;
            if (itrs.cycles - prevCycles > 1) {
                // cycles不一致了,则原来栈中的元素可能都没了
                shutdown();
                return true;
            }
            return false;
        }



void shutdown() {
            // assert lock.getHoldCount() == 1;
            //nextItem没有被置为null,通过next方法还可以返回
            cursor = NONE;
            if (nextIndex >= 0)
                nextIndex = REMOVED;
            if (lastRet >= 0) {
                lastRet = REMOVED;
                lastItem = null;
            }
            prevTakeIndex = DETACHED;
        }

boolean removedAt(int removedIndex) {
            // assert lock.getHoldCount() == 1;
            if (isDetached())
                return true;

            final int cycles = itrs.cycles;
            final int takeIndex = ArrayBlockingQueue.this.takeIndex;
            final int prevCycles = this.prevCycles;
            final int prevTakeIndex = this.prevTakeIndex;
            final int len = items.length;
            int cycleDiff = cycles - prevCycles;
            if (removedIndex < takeIndex)
                cycleDiff++;
            final int removedDistance =
                (cycleDiff * len) + (removedIndex - prevTakeIndex);
            // assert removedDistance >= 0;
            int cursor = this.cursor;
            //按照特定的逻辑重新计算cursor,lastRet,nextIndex等属性
            if (cursor >= 0) {
                int x = distance(cursor, prevTakeIndex, len);
                if (x == removedDistance) {
                    if (cursor == putIndex)
                        this.cursor = cursor = NONE;
                }
                else if (x > removedDistance) {
                    // assert cursor != prevTakeIndex;
                    this.cursor = cursor = dec(cursor);
                }
            }
            int lastRet = this.lastRet;
            if (lastRet >= 0) {
                int x = distance(lastRet, prevTakeIndex, len);
                if (x == removedDistance)
                    this.lastRet = lastRet = REMOVED;
                else if (x > removedDistance)
                    this.lastRet = lastRet = dec(lastRet);
            }
            int nextIndex = this.nextIndex;
            if (nextIndex >= 0) {
                int x = distance(nextIndex, prevTakeIndex, len);
                if (x == removedDistance)
                    this.nextIndex = nextIndex = REMOVED;
                else if (x > removedDistance)
                    this.nextIndex = nextIndex = dec(nextIndex);
            }
            else if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
                this.prevTakeIndex = DETACHED;
                return true;
            }
            return false;
        }

private int distance(int index, int prevTakeIndex, int length) {
            int distance = index - prevTakeIndex;
            if (distance < 0)
                distance += length;
            return distance;
        }

9、next / hasNext / remove

     这三个方法时Itr对Iterator接口的实现,如下:

public boolean hasNext() {
            // assert lock.getHoldCount() == 0;
            if (nextItem != null)
                return true;
            //如果没有下一个元素了    
            noNext();
            return false;
        }

public E next() {
            // assert lock.getHoldCount() == 0;
            final E x = nextItem;
            if (x == null)
                throw new NoSuchElementException();
            final ReentrantLock lock = ArrayBlockingQueue.this.lock;
            lock.lock();
            try {
                if (!isDetached())
                    incorporateDequeues();
                //如果isDetached为true还会继续执行    
                // assert nextIndex != NONE;
                // assert lastItem == null;
                lastRet = nextIndex;
                final int cursor = this.cursor;
                if (cursor >= 0) {
                    //获取指定cursor的元素
                    nextItem = itemAt(nextIndex = cursor);
                    //重新计算cursor,如果等于putIndex就将其置为None
                    this.cursor = incCursor(cursor);
                } else {
                    //已经遍历到putIndex处了,上次incCursor计算时将其变成负值
                    nextIndex = NONE;
                    nextItem = null;
                }
            } finally {
                lock.unlock();
            }
            return x;
        }

public void remove() {
            // assert lock.getHoldCount() == 0;
            final ReentrantLock lock = ArrayBlockingQueue.this.lock;
            lock.lock();
            try {
                if (!isDetached())
                    incorporateDequeues(); // might update lastRet or detach
                final int lastRet = this.lastRet;
                this.lastRet = NONE;
                if (lastRet >= 0) {
                    if (!isDetached())
                        //移除lastRet处的元素
                        removeAt(lastRet);
                    else {
                        final E lastItem = this.lastItem;
                        // assert lastItem != null;
                        this.lastItem = null;
                        if (itemAt(lastRet) == lastItem)
                            removeAt(lastRet);
                    }
                } else if (lastRet == NONE)
                    throw new IllegalStateException();

                if (cursor < 0 && nextIndex < 0)
                    detach(); //将当前Itr标记为无效并尝试清理掉
            } finally {
                lock.unlock();
            }
        }

private void noNext() {
            final ReentrantLock lock = ArrayBlockingQueue.this.lock;
            lock.lock();
            try {
                // assert cursor == NONE;
                // assert nextIndex == NONE;
                if (!isDetached()) {
                    //如果当前Itr还是有效的
                    incorporateDequeues(); // might update lastRet
                    if (lastRet >= 0) {
                        lastItem = itemAt(lastRet);
                        // assert lastItem != null;
                        detach();
                    }
                }
                
            } finally {
                lock.unlock();
            }
        }

boolean isDetached() {
            // assert lock.getHoldCount() == 1;
            return prevTakeIndex < 0;
        }

//校验并调整相关属性
private void incorporateDequeues() {

            final int cycles = itrs.cycles;
            final int takeIndex = ArrayBlockingQueue.this.takeIndex;
            final int prevCycles = this.prevCycles;
            final int prevTakeIndex = this.prevTakeIndex;

            if (cycles != prevCycles || takeIndex != prevTakeIndex) {
                final int len = items.length;
                // how far takeIndex has advanced since the previous
                // operation of this iterator
                long dequeues = (cycles - prevCycles) * len
                    + (takeIndex - prevTakeIndex);

                //校验各属性是否有效
                if (invalidated(lastRet, prevTakeIndex, dequeues, len))
                    lastRet = REMOVED;
                if (invalidated(nextIndex, prevTakeIndex, dequeues, len))
                    nextIndex = REMOVED;
                if (invalidated(cursor, prevTakeIndex, dequeues, len))
                    cursor = takeIndex;

                if (cursor < 0 && nextIndex < 0 && lastRet < 0)
                    detach();
                else {
                    //如果是有效的,则重置相关属性
                    this.prevCycles = cycles;
                    this.prevTakeIndex = takeIndex;
                }
            }
        }

//校验这个index是否有效,返回true表示无效
private boolean invalidated(int index, int prevTakeIndex,
                                    long dequeues, int length) {
            if (index < 0)
                return false;
            int distance = index - prevTakeIndex;
            if (distance < 0)
                distance += length;
            return dequeues > distance;
        }

private void detach() {
            if (prevTakeIndex >= 0) {
                //将当前Itr标记为无效的
                prevTakeIndex = DETACHED;
                //尝试将当前Itr从链表中移除
                itrs.doSomeSweeping(true);
            }
        }

private int incCursor(int index) {
            // assert lock.getHoldCount() == 1;
            if (++index == items.length)
                index = 0;
            if (index == putIndex)
                index = NONE;
            return index;
        }

 

你可能感兴趣的:(java8并发工具类源码解析)