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 中最簡單 且 最經常使用的方法,它自己其實還有不少實用的方法,好比預防超時之類的,之後會繼續分享。索引

相關文章
相關標籤/搜索