成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

阻塞隊(duì)列—ArrayBlockingQueue源碼分析

開(kāi)發(fā) 前端
ArrayBlockingQueue是一個(gè)阻塞隊(duì)列,內(nèi)部由ReentrantLock來(lái)實(shí)現(xiàn)線程安全,由Condition的await和signal來(lái)實(shí)現(xiàn)等待喚醒的功能。它的數(shù)據(jù)結(jié)構(gòu)是數(shù)組,準(zhǔn)確地說(shuō)是一個(gè)循環(huán)數(shù)組(可以類比一個(gè)圓環(huán)),所有的下標(biāo)在到達(dá)最大長(zhǎng)度時(shí)自動(dòng)從0繼續(xù)開(kāi)始。

 前言


ArrayBlockingQueue 由數(shù)組支持的有界阻塞隊(duì)列,隊(duì)列基于數(shù)組實(shí)現(xiàn),容量大小在創(chuàng)建 ArrayBlockingQueue 對(duì)象時(shí)已經(jīng)定義好。 此隊(duì)列按照先進(jìn)先出(FIFO)的原則對(duì)元素進(jìn)行排序。支持公平鎖和非公平鎖,默認(rèn)采用非公平鎖。其數(shù)據(jù)結(jié)構(gòu)如下圖:

阻塞隊(duì)列—ArrayBlockingQueue源碼分析

 

  • 注:每一個(gè)線程在獲取鎖的時(shí)候可能都會(huì)排隊(duì)等待,如果在等待時(shí)間上,先獲取鎖的線程和請(qǐng)求一定先被滿足,那么這個(gè)鎖就是公平的。反之,這個(gè)鎖就是不公平的。公平的獲取鎖,也就是當(dāng)前等待時(shí)間最長(zhǎng)的線程先獲取鎖

隊(duì)列創(chuàng)建

  1. BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(5); 

應(yīng)用場(chǎng)景

在線程池中有比較多的應(yīng)用,生產(chǎn)者消費(fèi)者場(chǎng)景。

  • 先進(jìn)先出隊(duì)列(隊(duì)列頭的是最先進(jìn)隊(duì)的元素;隊(duì)列尾的是最后進(jìn)隊(duì)的元素)
  • 有界隊(duì)列(即初始化時(shí)指定的容量,就是隊(duì)列最大的容量,不會(huì)出現(xiàn)擴(kuò)容,容量滿,則阻塞進(jìn)隊(duì)操作;容量空,則阻塞出隊(duì)操作)
  • 隊(duì)列不支持空元素
  • 公平性 (fairness)可以在構(gòu)造函數(shù)中指定。

此類支持對(duì)等待的生產(chǎn)者線程和使用者線程進(jìn)行排序的可選公平策略。默認(rèn)情況下,不保證是這種排序。然而,通過(guò)在構(gòu)造函數(shù)將公平性 (fairness) 設(shè)置為 true 而構(gòu)造的隊(duì)列允許按照 FIFO 順序訪問(wèn)線程。公平性通常會(huì)降低吞吐量,但也減少了可變性和避免了“不平衡性”。

工作原理

ArrayBlockingQueue是對(duì)BlockingQueue的一個(gè)數(shù)組實(shí)現(xiàn),它使用一把全局的鎖并行對(duì)queue的讀寫(xiě)操作,同時(shí)使用兩個(gè)Condition阻塞容量為空時(shí)的取操作和容量滿時(shí)的寫(xiě)操作。

基于 ReentrantLock 保證線程安全,根據(jù) Condition 實(shí)現(xiàn)隊(duì)列滿時(shí)的阻塞。

  1. final ReentrantLock lock; 
  2.  
  3. private final Condition notEmpty; 
  4.  
  5. private final Condition notFull; 

 Lock的作用是提供獨(dú)占鎖機(jī)制,來(lái)保護(hù)競(jìng)爭(zhēng)資源;而Condition是為了更加精細(xì)地對(duì)鎖進(jìn)行控制,它依賴于Lock,通過(guò)某個(gè)條件對(duì)多線程進(jìn)行控制。

notEmpty表示“鎖的非空條件”。當(dāng)某線程想從隊(duì)列中取數(shù)據(jù)時(shí),而此時(shí)又沒(méi)有數(shù)據(jù),則該線程通過(guò)notEmpty.await()進(jìn)行等待;當(dāng)其它線程向隊(duì)列中插入了元素之后,就調(diào)用notEmpty.signal()喚醒“之前通過(guò)notEmpty.await()進(jìn)入等待狀態(tài)的線程”。 同理,notFull表示“鎖的滿條件”。當(dāng)某線程想向隊(duì)列中插入元素,而此時(shí)隊(duì)列已滿時(shí),該線程等待;當(dāng)其它線程從隊(duì)列中取出元素之后,就喚醒該等待的線程。

  • 試圖向已滿隊(duì)列中放入元素會(huì)導(dǎo)致放入操作受阻塞,直到BlockingQueue里有新的喚空間才會(huì)被醒繼續(xù)操作; 試圖從空隊(duì)列中檢索元素將導(dǎo)致類似阻塞,直到BlocingkQueue進(jìn)了新貨才會(huì)被喚醒。

源碼分析

以下源碼分析基于JDK1.8

定義

ArrayBlockingQueue的類繼承關(guān)系如下:

  其包含的方法定義如下:

阻塞隊(duì)列—ArrayBlockingQueue源碼分析

 成員屬性

  1. /** 真正存入數(shù)據(jù)的數(shù)組 */ 
  2.    final Object[] items; 
  3.  
  4.    /** take,poll,peek or remove 的下一個(gè)索引 */ 
  5.    int takeIndex; 
  6.  
  7.    /** put,offer,or add 下一個(gè)索引 */ 
  8.    int putIndex; 
  9.  
  10.    /** 隊(duì)列中元素個(gè)數(shù) */ 
  11.    int count
  12.  
  13.    /** 可重入鎖 */ 
  14.    final ReentrantLock lock; 
  15.  
  16.    /** 如果數(shù)組是空的,在該Condition上等待 */ 
  17.    private final Condition notEmpty; 
  18.  
  19.    /** 如果數(shù)組是滿的,在該Condition上等待 */ 
  20.    private final Condition notFull; 
  21.  
  22.    /** 遍歷器實(shí)現(xiàn) */ 
  23.    transient Itrs itrs = null

 構(gòu)造函數(shù) 

  1. /** 
  2.     * 構(gòu)造函數(shù),設(shè)置隊(duì)列的初始容量 
  3.     */ 
  4.    public ArrayBlockingQueue(int capacity) { 
  5.        this(capacity, false); 
  6.    } 
  7.  
  8.    /** 
  9.     * 構(gòu)造函數(shù), 
  10.     * capacity and the specified access policy. 
  11.     * 
  12.     * @param capacity 設(shè)置數(shù)組大小 
  13.     * @param fair  設(shè)置是否為公平鎖 
  14.     * @throws IllegalArgumentException if {@code capacity < 1} 
  15.     */ 
  16.    public ArrayBlockingQueue(int capacity, boolean fair) { 
  17.        if (capacity <= 0) 
  18.            throw new IllegalArgumentException(); 
  19.        this.items = new Object[capacity]; 
  20.        // 是否為公平鎖,如果是的話,那么先到的線程先獲得鎖對(duì)象 
  21.        // 否則,由操作系統(tǒng)調(diào)度由哪個(gè)線程獲得鎖,一般為false,性能會(huì)比較高 
  22.        lock = new ReentrantLock(fair);  
  23.        notEmpty = lock.newCondition(); 
  24.        notFull =  lock.newCondition(); 
  25.    } 
  26.  
  27.    /** 
  28.     * 構(gòu)造函數(shù),帶有初始內(nèi)容的隊(duì)列 
  29.     */ 
  30.    public ArrayBlockingQueue(int capacity, boolean fair, 
  31.                              Collection<? extends E> c) { 
  32.        this(capacity, fair); 
  33.  
  34.        final ReentrantLock lock = this.lock; 
  35.        //加鎖的目的是為了其他CPU能夠立即看到修改 
  36.        //加鎖和解鎖底層都是CAS,會(huì)強(qiáng)制修改寫(xiě)回主存,對(duì)其他CPU可見(jiàn) 
  37.        lock.lock(); // 要給數(shù)組設(shè)置內(nèi)容,先上鎖 
  38.        try { 
  39.            int i = 0; 
  40.            try { 
  41.                for (E e : c) { 
  42.                    checkNotNull(e); 
  43.                    items[i++] = e; // 依次拷貝內(nèi)容 
  44.                } 
  45.            } catch (ArrayIndexOutOfBoundsException ex) { 
  46.                throw new IllegalArgumentException(); 
  47.            } 
  48.            count = i; 
  49.            putIndex = (i == capacity) ? 0 : i; // 如果 putIndex大于數(shù)組大小,那么從0重寫(xiě)開(kāi)始 
  50.        } finally { 
  51.            lock.unlock(); // 最后一定要釋放鎖 
  52.        } 
  53.    } 

 入隊(duì)方法

add / offer / put,這三個(gè)方法都是往隊(duì)列中添加元素,說(shuō)明如下:

  • add方法依賴于offer方法,如果隊(duì)列滿了則拋出異常,否則添加成功返回true;
  • offer方法有兩個(gè)重載版本,只有一個(gè)參數(shù)的版本,如果隊(duì)列滿了就返回false,否則加入到隊(duì)列中,返回true,add方法就是調(diào)用此版本的offer方法;另一個(gè)帶時(shí)間參數(shù)的版本,如果隊(duì)列滿了則等待,可指定等待的時(shí)間,如果這期間中斷了則拋出異常,如果等待超時(shí)了則返回false,否則加入到隊(duì)列中返回true;
  • put方法跟帶時(shí)間參數(shù)的offer方法邏輯一樣,不過(guò)沒(méi)有等待的時(shí)間限制,會(huì)一直等待直到隊(duì)列有空余位置了,再插入到隊(duì)列中,返回true
  1. /** 
  2.      * 添加一個(gè)元素,其實(shí)super.add里面調(diào)用了offer方法 
  3.      */ 
  4.     public boolean add(E e) { 
  5.         return super.add(e); 
  6.     } 
  7.  
  8.     /** 
  9.      * 加入成功返回 true,否則返回 false 
  10.      */ 
  11.     public boolean offer(E e) { 
  12.      // 創(chuàng)建插入的元素是否為null,是的話拋出NullPointerException異常 
  13.         checkNotNull(e); 
  14.         // 獲取“該阻塞隊(duì)列的獨(dú)占鎖” 
  15.         final ReentrantLock lock = this.lock; 
  16.         lock.lock(); // 上鎖 
  17.         try { 
  18.          // 如果隊(duì)列已滿,則返回false。 
  19.             if (count == items.length) // 超過(guò)數(shù)組的容量 
  20.                 return false
  21.             else { 
  22.              // 如果隊(duì)列未滿,則插入e,并返回true。 
  23.                 enqueue(e);  
  24.                 return true
  25.             } 
  26.         } finally { 
  27.          // 釋放鎖 
  28.             lock.unlock(); 
  29.         } 
  30.     } 
  31.  
  32.     /** 
  33.      * 如果隊(duì)列已滿的話,就會(huì)等待 
  34.      */ 
  35.     public void put(E e) throws InterruptedException { 
  36.         checkNotNull(e); 
  37.         final ReentrantLock lock = this.lock; 
  38.         lock.lockInterruptibly(); //和lock方法的區(qū)別是讓它在阻塞時(shí)可以拋出異常跳出 
  39.         try { 
  40.             while (count == items.length) 
  41.                 notFull.await(); // 這里就是阻塞了,要注意:如果運(yùn)行到這里,那么它會(huì)釋放上面的鎖,一直等到 notify 
  42.             enqueue(e); 
  43.         } finally { 
  44.             lock.unlock(); 
  45.         } 
  46.     } 
  47.  
  48.     /** 
  49.      * 帶有超時(shí)事件的插入方法,unit 表示是按秒、分、時(shí)哪一種 
  50.      */ 
  51.     public boolean offer(E e, long timeout, TimeUnit unit) 
  52.         throws InterruptedException { 
  53.  
  54.         checkNotNull(e); 
  55.         long nanos = unit.toNanos(timeout); 
  56.         final ReentrantLock lock = this.lock; 
  57.         lock.lockInterruptibly(); 
  58.         try { 
  59.             while (count == items.length) { 
  60.                 if (nanos <= 0) 
  61.                     return false
  62.                 nanos = notFull.awaitNanos(nanos); // 帶有超時(shí)等待的阻塞方法 
  63.             } 
  64.             enqueue(e); // 入隊(duì) 
  65.             return true
  66.         } finally { 
  67.             lock.unlock(); 
  68.         } 
  69.     } 

 出隊(duì)方法

poll / take / peek,這幾個(gè)方法都是獲取隊(duì)列頂?shù)脑?,具體說(shuō)明如下:

  • poll方法有兩個(gè)重載版本,第一個(gè)版本,如果隊(duì)列是空的,返回null,否則移除并返回隊(duì)列頭部元素;另一個(gè)帶時(shí)間參數(shù)的版本,如果棧為空則等待,可以指定等待的時(shí)間,如果等待超時(shí)了則返回null,如果被中斷了則拋出異常,否則移除并返回棧頂元素
  • take方法同帶時(shí)間參數(shù)的poll方法,但是不能指定等待時(shí)間,會(huì)一直等待直到隊(duì)列中有元素為止,然后移除并返回棧頂元素
  • peek方法只是返回隊(duì)列頭部元素,不移除
  1. // 實(shí)現(xiàn)的方法,如果當(dāng)前隊(duì)列為空,返回null 
  2.    public E poll() { 
  3.        final ReentrantLock lock = this.lock; 
  4.        lock.lock(); 
  5.        try { 
  6.            return (count == 0) ? null : dequeue(); 
  7.        } finally { 
  8.            lock.unlock(); 
  9.        } 
  10.    } 
  11. // 實(shí)現(xiàn)的方法,如果當(dāng)前隊(duì)列為空,一直阻塞 
  12.    public E take() throws InterruptedException { 
  13.        final ReentrantLock lock = this.lock; 
  14.        lock.lockInterruptibly(); 
  15.        try { 
  16.            while (count == 0) 
  17.                notEmpty.await(); // 隊(duì)列為空,阻塞方法 
  18.            return dequeue(); 
  19.        } finally { 
  20.            lock.unlock(); 
  21.        } 
  22.    } 
  23. // 帶有超時(shí)事件的取元素方法,否則返回null 
  24.    public E poll(long timeout, TimeUnit unit) throws InterruptedException { 
  25.        long nanos = unit.toNanos(timeout); 
  26.        final ReentrantLock lock = this.lock; 
  27.        lock.lockInterruptibly(); 
  28.        try { 
  29.            while (count == 0) { 
  30.                if (nanos <= 0) 
  31.                    return null
  32.                nanos = notEmpty.awaitNanos(nanos); // 超時(shí)等待 
  33.            } 
  34.            return dequeue(); // 取得元素 
  35.        } finally { 
  36.            lock.unlock(); 
  37.        } 
  38.    } 
  39.  
  40.    // 只是看一個(gè)隊(duì)列最前面的元素,取出是不擅長(zhǎng)隊(duì)列中原來(lái)的元素,隊(duì)列為空時(shí)返回null 
  41.    public E peek() { 
  42.        final ReentrantLock lock = this.lock; 
  43.        lock.lock(); 
  44.        try { 
  45.            return itemAt(takeIndex); // 隊(duì)列為空時(shí)返回null 
  46.        } finally { 
  47.            lock.unlock(); 
  48.        } 
  49.    } 

 刪除元素方法

remove / clear /drainT,這三個(gè)方法用于從隊(duì)列中移除元素,具體說(shuō)明如下:

  • remove方法用于移除某個(gè)元素,如果棧為空或者沒(méi)有找到該元素則返回false,否則從棧中移除該元素;移除時(shí),如果該元素位于棧頂則直接移除,如果位于棧中間,則需要將該元素后面的其他元素往前面挪動(dòng),移除后需要喚醒因?yàn)闂M了而阻塞的線程
  • clear方法用于整個(gè)棧,同時(shí)將takeIndex置為putIndex,保證棧中的元素先進(jìn)先出;最后會(huì)喚醒最多count個(gè)線程,因?yàn)檎R粋€(gè)線程插入一個(gè)元素,如果喚醒超過(guò)count個(gè)線程,可能導(dǎo)致部分線程因?yàn)闂M了又再次被阻塞
  • drainTo方法有兩個(gè)重載版本,一個(gè)是不帶個(gè)數(shù),將所有的元素都移除并拷貝到指定的集合中;一個(gè)帶個(gè)數(shù),將指定個(gè)數(shù)的元素移除并拷貝到指定的集合中,兩者的底層實(shí)現(xiàn)都是同一個(gè)方法。移除后需要重置takeIndex和count,并喚醒最多移除個(gè)數(shù)的因?yàn)闂M而阻塞的線程。
  1. /** 
  2.     * 從隊(duì)列中刪除一個(gè)元素的方法。刪除成功返回true,否則返回false 
  3.     */ 
  4.    public boolean remove(Object o) { 
  5.        if (o == nullreturn false
  6.        final Object[] items = this.items; 
  7.        final ReentrantLock lock = this.lock; 
  8.        lock.lock(); 
  9.        try { 
  10.            if (count > 0) { 
  11.                final int putIndex = this.putIndex; 
  12.                int i = takeIndex; 
  13.                //從takeIndex開(kāi)始往后遍歷直到等于putIndex 
  14.                do { 
  15.                    if (o.equals(items[i])) { 
  16.                        removeAt(i); // 真正刪除的方法 
  17.                        return true
  18.                    } 
  19.                    //走到數(shù)組末尾了又從頭開(kāi)始,put時(shí)也按照這個(gè)規(guī)則來(lái) 
  20.                    if (++i == items.length) 
  21.                        i = 0; 
  22.                } while (i != putIndex); // 一直不斷的循環(huán)取出來(lái)做判斷 
  23.            } 
  24.            //如果數(shù)組為空,返回false 
  25.            return false
  26.        } finally { 
  27.            lock.unlock(); 
  28.        } 
  29.    } 
  30.  
  31. /** 
  32.     * 指定刪除索引上的元素. 
  33.     */ 
  34.    void removeAt(final int removeIndex) { 
  35.        // assert lock.getHoldCount() == 1; 
  36.        // assert items[removeIndex] != null
  37.        // assert removeIndex >= 0 && removeIndex < items.length; 
  38.        final Object[] items = this.items; 
  39.        if (removeIndex == takeIndex) { 
  40.            //如果移除的就是棧頂?shù)脑?nbsp;
  41.            items[takeIndex] = null
  42.            if (++takeIndex == items.length) 
  43.                takeIndex = 0; 
  44.            //元素個(gè)數(shù)減1 
  45.            count--; 
  46.            if (itrs != null
  47.                itrs.elementDequeued(); 
  48.        } else { 
  49.            // an "interior" remove 
  50.  
  51.            // 如果移除的是棧中間的某個(gè)元素,需要將該元素后面的元素往前挪動(dòng) 
  52.            final int putIndex = this.putIndex; 
  53.            for (int i = removeIndex;;) { 
  54.                int next = i + 1; 
  55.                //到數(shù)組末尾了,從頭開(kāi)始 
  56.                if (next == items.length) 
  57.                    next = 0; 
  58.                if (next != putIndex) { 
  59.                 //將后面一個(gè)元素復(fù)制到前面來(lái) 
  60.                    items[i] = items[next]; 
  61.                    i = next
  62.                } else { 
  63.                 //如果下一個(gè)元素的索引等于putIndex,說(shuō)明i就是棧中最后一個(gè)元素了,直接將該元素置為null 
  64.                    items[i] = null
  65.                    //重置putIndex為i 
  66.                    this.putIndex = i; 
  67.                    break; 
  68.                } 
  69.            } 
  70.            count--; 
  71.            if (itrs != null
  72.             //通知itrs節(jié)點(diǎn)移除了 
  73.                itrs.removedAt(removeIndex); 
  74.        } 
  75.        //喚醒因?yàn)闂M了而等待的線程 
  76.        notFull.signal(); // 有一個(gè)元素刪除成功,那肯定隊(duì)列不滿 
  77.    } 
  78.  
  79. /** 
  80.     * 清空隊(duì)列 
  81.     */ 
  82.    public void clear() { 
  83.        final Object[] items = this.items; 
  84.        final ReentrantLock lock = this.lock; 
  85.        lock.lock(); 
  86.        try { 
  87.            int k = count
  88.            if (k > 0) { 
  89.                final int putIndex = this.putIndex; 
  90.                int i = takeIndex; 
  91.                //從takeIndex開(kāi)始遍歷直到i等于putIndex,將數(shù)組元素置為null 
  92.                do { 
  93.                    items[i] = null
  94.                    if (++i == items.length) 
  95.                        i = 0; 
  96.                } while (i != putIndex); 
  97.                //注意此處沒(méi)有將這兩個(gè)index置為0,只是讓他們相等,因?yàn)橹灰嗟染涂梢詫?shí)現(xiàn)棧先進(jìn)先出了 
  98.                takeIndex = putIndex; 
  99.                count = 0; 
  100.                if (itrs != null
  101.                    itrs.queueIsEmpty(); 
  102.                //如果有因?yàn)闂M了而等待的線程,則將其喚醒 
  103.                //注意這里沒(méi)有使用signalAll而是通過(guò)for循環(huán)來(lái)signal多次,單純從喚醒線程來(lái)看是可以使用signalAll的,效果跟這里的for循環(huán)是一樣的 
  104.                //如果有等待的線程,說(shuō)明count就是當(dāng)前線程的最大容量了,這里清空了,最多只能put count次,一個(gè)線程只能put 1次,只喚醒最多count個(gè)線程就避免了 
  105.                //線程被喚醒后再次因?yàn)闂M了而阻塞 
  106.                for (; k > 0 && lock.hasWaiters(notFull); k--) 
  107.                    notFull.signal(); 
  108.            } 
  109.        } finally { 
  110.            lock.unlock(); 
  111.        } 
  112.    } 
  113.  
  114.    /** 
  115.     * 取出所有元素到集合 
  116.     */ 
  117.    public int drainTo(Collection<? super E> c) { 
  118.        return drainTo(c, Integer.MAX_VALUE); 
  119.    } 
  120.  
  121.    /** 
  122.     * 取出所有元素到集合 
  123.     */ 
  124.    public int drainTo(Collection<? super E> c, int maxElements) { 
  125.        //校驗(yàn)參數(shù)合法 
  126.        checkNotNull(c); 
  127.        if (c == this) 
  128.            throw new IllegalArgumentException(); 
  129.        if (maxElements <= 0) 
  130.            return 0; 
  131.        final Object[] items = this.items; 
  132.        final ReentrantLock lock = this.lock; 
  133.        lock.lock(); 
  134.        try { 
  135.         //取兩者之間的最小值 
  136.            int n = Math.min(maxElements, count); 
  137.            int take = takeIndex; 
  138.            int i = 0; 
  139.            try { 
  140.             //從takeIndex開(kāi)始遍歷,取出元素然后添加到c中,直到滿足個(gè)數(shù)要求為止 
  141.                while (i < n) { 
  142.                    @SuppressWarnings("unchecked"
  143.                    E x = (E) items[take]; 
  144.                    c.add(x); 
  145.                    items[take] = null
  146.                    if (++take == items.length) 
  147.                        take = 0; 
  148.                    i++; 
  149.                } 
  150.                return n; 
  151.            } finally { 
  152.                // Restore invariants even if c.add() threw 
  153.                if (i > 0) { 
  154.                 //取完了,修改count減去i 
  155.                    count -= i; 
  156.                    takeIndex = take; 
  157.                    if (itrs != null) { 
  158.                        if (count == 0) 
  159.                         //通知itrs ??樟?nbsp;
  160.                            itrs.queueIsEmpty(); 
  161.                        else if (i > take) 
  162.                         //說(shuō)明take中間變成0了,通知itrs 
  163.                            itrs.takeIndexWrapped(); 
  164.                    } 
  165.                    //喚醒在因?yàn)闂M而等待的線程,最多喚醒i個(gè),同上避免線程被喚醒了因?yàn)闂S譂M了而阻塞 
  166.                    for (; i > 0 && lock.hasWaiters(notFull); i--) 
  167.                        notFull.signal(); 
  168.                } 
  169.            } 
  170.        } finally { 
  171.            lock.unlock(); 
  172.        } 
  173.    } 

 iterator / Itr / Itrs

Itr和Itrs都是ArrayBlockingQueue的兩個(gè)內(nèi)部類,如下:

阻塞隊(duì)列—ArrayBlockingQueue源碼分析

 iterator方法返回一個(gè)迭代器實(shí)例,用于實(shí)現(xiàn)for循環(huán)遍歷和部分Collection接口,該方法的實(shí)現(xiàn)如下: 

  1. public Iterator<E> iterator() { 
  2.  return new Itr(); 
  3.  
  4. Itr() { 
  5.  // assert lock.getHoldCount() == 0; 
  6.  lastRet = NONE; 
  7.  final ReentrantLock lock = ArrayBlockingQueue.this.lock; 
  8.     lock.lock(); 
  9.     try { 
  10.      if (count == 0) { 
  11.          //NONE和DETACHED都是常量 
  12.             cursor = NONE; 
  13.             nextIndex = NONE; 
  14.             prevTakeIndex = DETACHED; 
  15.         } else { 
  16.          //初始化各屬性 
  17.             final int takeIndex = ArrayBlockingQueue.this.takeIndex; 
  18.             prevTakeIndex = takeIndex; 
  19.             nextItem = itemAt(nextIndex = takeIndex); 
  20.             cursor = incCursor(takeIndex); 
  21.             if (itrs == null) { 
  22.              itrs = new Itrs(this); 
  23.             } else { 
  24.              //初始化Itrs,將當(dāng)前線程注冊(cè)到Itrs 
  25.                 itrs.register(this); // in this order 
  26.                 itrs.doSomeSweeping(false); 
  27.             } 
  28.             prevCycles = itrs.cycles; 
  29.             // assert takeIndex >= 0; 
  30.             // assert prevTakeIndex == takeIndex; 
  31.             // assert nextIndex >= 0; 
  32.             // assert nextItem != null
  33.      } 
  34.  } finally { 
  35.     lock.unlock(); 
  36.     } 
  37.  
  38. Itrs(Itr initial) { 
  39.  register(initial); 
  40.  
  41. //根據(jù)index計(jì)算cursor 
  42. private int incCursor(int index) { 
  43.  // assert lock.getHoldCount() == 1; 
  44.  if (++index == items.length) 
  45.   index = 0; 
  46.  if (index == putIndex) 
  47.   index = NONE; 
  48.  return index
  49.  
  50. /** 
  51. * 創(chuàng)建一個(gè)新的Itr實(shí)例時(shí),會(huì)調(diào)用此方法將該實(shí)例添加到Node鏈表中 
  52. */ 
  53. void register(Itr itr) { 
  54.  //創(chuàng)建一個(gè)新節(jié)點(diǎn)將其插入到head節(jié)點(diǎn)的前面 
  55.  head = new Node(itr, head); 

 小結(jié)

ArrayBlockingQueue是一個(gè)阻塞隊(duì)列,內(nèi)部由ReentrantLock來(lái)實(shí)現(xiàn)線程安全,由Condition的await和signal來(lái)實(shí)現(xiàn)等待喚醒的功能。它的數(shù)據(jù)結(jié)構(gòu)是數(shù)組,準(zhǔn)確地說(shuō)是一個(gè)循環(huán)數(shù)組(可以類比一個(gè)圓環(huán)),所有的下標(biāo)在到達(dá)最大長(zhǎng)度時(shí)自動(dòng)從0繼續(xù)開(kāi)始。

PS:以上代碼提交在 Github :

https://github.com/Niuh-Study/niuh-juc-final.git

 

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2020-11-20 06:22:02

LinkedBlock

2020-11-24 09:04:55

PriorityBlo

2020-11-25 14:28:56

DelayedWork

2023-12-28 07:49:11

線程池源碼應(yīng)用場(chǎng)景

2017-04-12 10:02:21

Java阻塞隊(duì)列原理分析

2025-01-14 00:00:00

Blocking隊(duì)列元素

2012-06-14 10:34:40

Java阻塞搜索實(shí)例

2025-04-03 07:41:55

API阻塞隊(duì)列數(shù)據(jù)

2023-12-15 09:45:21

阻塞接口

2021-05-17 07:36:54

ArrayBlocki面試集合

2025-04-02 01:20:00

阻塞隊(duì)列源碼

2021-06-04 14:15:10

鴻蒙HarmonyOS應(yīng)用

2022-06-30 08:14:05

Java阻塞隊(duì)列

2022-09-26 00:48:14

線程池阻塞數(shù)據(jù)

2024-10-14 12:34:08

2024-02-20 08:16:10

阻塞隊(duì)列源碼

2011-03-15 11:33:18

iptables

2014-08-26 11:11:57

AsyncHttpCl源碼分析

2021-09-22 14:36:32

鴻蒙HarmonyOS應(yīng)用

2023-12-05 13:46:09

解密協(xié)程線程隊(duì)列
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩欧美一级 | 精品欧美一区免费观看α√ | 2022精品国偷自产免费观看 | 欧美最猛黑人xxxⅹ 粉嫩一区二区三区四区公司1 | av免费看在线 | 国产精品久久久亚洲 | 亚州精品天堂中文字幕 | 欧美性大战xxxxx久久久 | 免费在线播放黄色 | 久久99精品久久久久久 | 99久久久久久 | 99视频免费在线观看 | 毛片a| 欧美一区两区 | 日一区二区三区 | 国产精品久久久久永久免费观看 | 中文字幕一区二区三区四区五区 | 亚洲一区二区三区四区五区中文 | 91精品国产乱码麻豆白嫩 | 黄色毛片免费 | 91免费看片 | 给我免费的视频在线观看 | 欧洲亚洲视频 | 精品一区二区三区四区五区 | 久久久精品久久 | 欧美日韩在线一区二区 | 一级毛片视频在线 | 新91视频网 | 国产婷婷精品av在线 | 亚洲日本激情 | 免费观看色 | 一区二区三区四区在线视频 | 国产日韩精品一区 | 欧美一区二区三区在线观看 | 国产乱人伦 | 91tv在线观看 | 99视频免费播放 | 免费不卡av | 国产区在线观看 | 精品视频99 | 成人性生交大片 |