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的類繼承關係如下:

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

上圖中的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<? extends E> 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<? super E> c) {
        return drainTo(c, Integer.MAX_VALUE);
    }

public int drainTo(Collection<? super E> 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<E> 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的一個內部類,其定義如下:

注意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;
        }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章