Java併發之ArrayBlockingQueue

 ArrayBlockingQueue是一個由數組支持的有界阻塞隊列。此隊列按 FIFO(先進先出)原則對元素進行排序。隊列的頭部是在隊列中存在時間最長的元素。隊列的尾部是在隊列中存在時間最短的元素。新元素插入到隊列的尾部,隊列獲取操做則是從隊列頭部開始得到元素。 數組

        ArrayBlockingQueue繼承自 AbstractQueue並實現 BlockingQueue接口。緩存

 

        ArrayBlockingQueue是一個典型的「有界緩存區」,固定大小的數組在其中保持生產者插入的元素和使用者提取的元素。一旦建立了這樣的緩存區,就不能再增長其容量。試圖向已滿隊列中放入元素會致使操做受阻塞,試圖從空隊列中提取元素將致使相似阻塞。 多線程

        ArrayBlockingQueue支持對等待的生產者線程和使用者線程進行排序的可選公平策略。默認狀況下,不保證是這種排序。然而,經過將公平性 (fairness) 設置爲 true 而構造的隊列容許按照 FIFO 順序訪問線程。公平性一般會下降吞吐量,但也減小了可變性和避免了「不平衡性」。 公平性經過建立 ArrayBlockingQueue實例時指定。學習

 

        1.成員變量this

Java代碼   收藏代碼
  1. /** 隊列數組實現 */  
  2. private final E[] items;  
  3. /** 已取出元素索引,用於下一個元素的 take, poll or remove */  
  4. private int takeIndex;  
  5. /** 已插入元素索引,用於下一個元素的 put, offer, or add */  
  6. private int putIndex;  
  7. /** 隊列中項目數 */  
  8. private int count;  
  9. /** 保護全部訪問的主鎖 */  
  10. private final ReentrantLock lock;  
  11. /** Condition 實例,用於等待中 take */  
  12. private final Condition notEmpty;  
  13. /** Condition 實例,用於等待中 put*/  
  14. private final Condition notFull;  

        以前咱們已經學習了鎖相關的知識,因此幾個成員變量不難理解。spa

        1)其中E[] items;是數組式的隊列實現;線程

        2)takeIndex 用於記錄 take操做的次數;指針

        3)putIndex 用於記錄 put操做的次數;blog

        4)count 用於記錄隊列中元素數目;排序

        5)ReentrantLock lock 是用於控制訪問的主鎖;

        6)Condition notEmpty 獲取操做時的條;

        7)Condition notFull 插入操做時的條件;

 

        2.構造方法

        ArrayBlockingQueue的構造方法有3個。

        1)最簡單的構造方法:

Java代碼   收藏代碼
  1. //指定隊列大小  
  2. public ArrayBlockingQueue(int capacity) {  
  3.     this(capacity, false);  
  4. }  

        此種構造方法最爲簡單也最爲經常使用,在建立 ArrayBlockingQueue實例時只需指定其大小便可。

Java代碼   收藏代碼
  1. BlockingQueue<Object> q = new ArrayBlockingQueue<Object>(10);  

        2)增長訪問策略的構造方法,除了指定隊列大小外還可指定隊列的訪問策略:

Java代碼   收藏代碼
  1. //指定隊列大小、訪問策略  
  2. public ArrayBlockingQueue(int capacity, boolean fair) {  
  3.     if (capacity <= 0)  
  4.         throw new IllegalArgumentException();  
  5.     this.items = (E[]) new Object[capacity];  
  6.     lock = new ReentrantLock(fair);  
  7.     notEmpty = lock.newCondition();  
  8.     notFull = lock.newCondition();  
  9. }  

        fair若是爲 true,則按照 FIFO 順序訪問插入或移除時受阻塞線程的隊列;若是爲 false,則訪問順序是不肯定的。

        構造方法中首先初始化了 items數組,而後根據fair建立 ReentrantLock實例,最後返回 notEmpty與 notFull兩個 Condition實例,分別用於等待中的獲取與添加操做。

        3)帶初始元素的構造方法:

Java代碼   收藏代碼
  1. //指定隊列大小、訪問策略、初始元素  
  2. public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) {  
  3.     this(capacity, fair);  
  4.     if (capacity < c.size())  
  5.         throw new IllegalArgumentException();  
  6.   
  7.     for (Iterator<? extends E> it = c.iterator(); it.hasNext();)  
  8.         add(it.next());  
  9. }  

        除了能夠指定容量和訪問策略外,還能夠包含給定 collection 的元素,並以 collection 迭代器的遍歷順序添加元素。

        代碼也能夠觀察到,在實例化隊列以後還使用了add方法將 collection 中的元素按原有順序添加到實例中。

 

        3.添加元素

        1)add方法

        ArrayBlockingQueue的add方法調用的是父類方法,而父類 add方法則調用的是 offer方法,如下是add方法的源代碼:

Java代碼   收藏代碼
  1. public boolean add(E e) {  
  2.     //調用父類add方法  
  3.     return super.add(e);  
  4. }  

        2)offer方法

        offer方法將指定的元素插入到此隊列的尾部(若是當即可行且不會超過該隊列的容量),在成功時返回 true,若是此隊列已滿,則返回 false。此方法一般要優於 add(E) 方法,後者可能沒法插入元素,而只是拋出一個異常。 

Java代碼   收藏代碼
  1. /** 
  2.  * 將指定的元素插入到此隊列的尾部(若是當即可行且不會超過該隊列的容量), 
  3.  * 在成功時返回 true,若是此隊列已滿,則返回 false。 
  4.  * 此方法一般要優於 add(E) 方法,後者可能沒法插入元素,而只是拋出一個異常。 
  5.  */  
  6. public boolean offer(E e) {  
  7.     //判斷e是否爲null  
  8.     if (e == null)  
  9.         throw new NullPointerException();  
  10.     final ReentrantLock lock = this.lock;  
  11.     //獲取鎖  
  12.     lock.lock();  
  13.     try {  
  14.         //判斷隊列是否已滿  
  15.         if (count == items.length)  
  16.             return false;  
  17.         else {  
  18.             //若是未滿則插入  
  19.             insert(e);  
  20.             return true;  
  21.         }  
  22.     } finally {  
  23.         //釋放鎖  
  24.         lock.unlock();  
  25.     }  
  26. }  

        由於 add方法在隊列已滿時會拋出異常,因此 offer方法通常優於 add方法使用。

        首先,判斷要添加的元素是否爲 null,若是爲null則拋出空指針異常。

        接着,建立一個 ReentrantLock實例,ReentrantLock是可重入鎖實現。更詳細介紹參考http://286.iteye.com/blog/2296191

        而後,獲取鎖。

        最後,判斷隊列是否已滿,若是已滿則返回 false;若是未滿則調用insert方法插入元素,返回true。

        全部操做完成後釋放鎖。

        offer方法的處理流程能夠參照如下流程圖:



        從代碼中就能夠看到,offer方法利用了ReentrantLock來實現隊列阻塞的功能,因此多線程操做相同隊列時會排隊等待。

        offer的另外一個重載方法是 offer(E e, long timeout, TimeUnit unit),此重載方法將指定的元素插入此隊列的尾部,若是該隊列已滿,則在到達指定的等待時間以前等待可用的空間。其源代碼爲:

Java代碼   收藏代碼
  1. /** 
  2.  * 將指定的元素插入此隊列的尾部,若是該隊列已滿,則在到達指定的等待時間以前等待可用的空間。 
  3.  */  
  4. public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {  
  5.   
  6.     if (e == null)  
  7.         throw new NullPointerException();  
  8.     long nanos = unit.toNanos(timeout);  
  9.     final ReentrantLock lock = this.lock;  
  10.     lock.lockInterruptibly();  
  11.     try {  
  12.         for (;;) {  
  13.             if (count != items.length) {  
  14.                 insert(e);  
  15.                 return true;  
  16.             }  
  17.             if (nanos <= 0)  
  18.                 return false;  
  19.             try {  
  20.                 nanos = notFull.awaitNanos(nanos);  
  21.             } catch (InterruptedException ie) {  
  22.                 notFull.signal(); // propagate to non-interrupted thread  
  23.                 throw ie;  
  24.             }  
  25.         }  
  26.     } finally {  
  27.         lock.unlock();  
  28.     }  
  29. }  

        與普通offer方法不一樣之處在於:offer(E e, long timeout, TimeUnit unit)方法利用循環在指定時間內不斷去嘗試添加元素,若是成功則返回true,若是指定時間已到則退出返回 false。

        3)insert方法

        insert方法在當前位置(putIndex)插入元素。

Java代碼   收藏代碼
  1. /** 
  2.  * 在當前位置(putIndex)插入元素(在得到鎖的狀況下調用) 
  3.  */  
  4. private void insert(E x) {  
  5.     //設置 putIndex位置 items數組元素爲x  
  6.     items[putIndex] = x;  
  7.     //返回putIndex新值,若是已滿則返回0,未滿則+1  
  8.     putIndex = inc(putIndex);  
  9.     //增長元素數量  
  10.     ++count;  
  11.     //喚醒獲取線程  
  12.     notEmpty.signal();  
  13. }  

        由於 ArrayBlockingQueue內部隊列實現爲數組items,而 putIndex則記錄了隊列中已添加元素的位置,因此新添加的元素就直接被添加到數組的指定位置。隨後修改 putIndex值,若是隊列未滿則+1,若是已滿則從0從新開始。最後喚醒 notEmpty中的一個線程。

 

        4)put方法

        將指定的元素插入此隊列的尾部,若是該隊列已滿,則等待可用的空間。

        如下是put方法的源代碼:

Java代碼   收藏代碼
  1. /** 
  2.  * 將指定的元素插入此隊列的尾部,若是該隊列已滿,則等待可用的空間 
  3.  */  
  4. public void put(E e) throws InterruptedException {  
  5.     //判斷e是否爲null  
  6.     if (e == null)  
  7.         throw new NullPointerException();  
  8.     final E[] items = this.items;  
  9.     final ReentrantLock lock = this.lock;  
  10.     //獲取中斷鎖  
  11.     lock.lockInterruptibly();  
  12.     try {  
  13.         try {  
  14.             //利用循環判斷隊列是否已滿  
  15.             while (count == items.length)  
  16.                 //若是已滿則調用await方法阻塞等待  
  17.                 notFull.await();  
  18.         } catch (InterruptedException ie) {  
  19.             notFull.signal(); // propagate to non-interrupted thread  
  20.             throw ie;  
  21.         }  
  22.         //隊列未滿則插入  
  23.         insert(e);  
  24.     } finally {  
  25.         //釋放鎖  
  26.         lock.unlock();  
  27.     }  
  28. }  

        put方法與其餘方法相似,其中會循環判斷隊列是否已滿,若是已滿則阻塞 notFull,若是未滿則調用 insert方法添加元素。由於其中運用了循環判斷隊列是否有位置添加新元素,若是隊列已滿則產生阻塞等待,直至能夠添加元素爲止。

        將本文開始時的例子修改一下,去掉消費者,只留下生產者,這樣當隊列滿了以後沒有消費者去消費產品,生產者就不會再向隊列中插入了:

Java代碼   收藏代碼
  1. class Producer implements Runnable {  
  2.     private final ArrayBlockingQueue<Integer> queue;  
  3.     private int i;  
  4.   
  5.     Producer(ArrayBlockingQueue<Integer> q) {  
  6.         queue = q;  
  7.     }  
  8.   
  9.     public void run() {  
  10.         try {  
  11.             while (true) {  
  12.                 int p=produce();  
  13.                 queue.put(p);// 將產品放入緩衝隊列  
  14.                 System.out.println("插入成功:"+p);  
  15.             }  
  16.         } catch (InterruptedException e) {  
  17.             e.printStackTrace();  
  18.         }  
  19.     }  
  20.   
  21.     int produce() {  
  22.         return i++;// 生產產品  
  23.     }  
  24. }  
  25.   
  26. public class Runner {  
  27.     public static void main(String[] args) {  
  28.         ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(10);  
  29.         Producer p = new Producer(q);  
  30.         new Thread(p).start();  
  31.     }  
  32. }  
  33. //結果:  
  34. 插入成功:0  
  35. 插入成功:1  
  36. 插入成功:2  
  37. 插入成功:3  
  38. 插入成功:4  
  39. 插入成功:5  
  40. 插入成功:6  
  41. 插入成功:7  
  42. 插入成功:8  
  43. 插入成功:9  

        此時程序並不會退出,而是阻塞在那裏等待隊列有位置插入。

 

        4.獲取元素

        1)peek方法

        獲取但不移除此隊列的頭;若是此隊列爲空,則返回 null。如下是peek方法的源代碼:

Java代碼   收藏代碼
  1. /** 
  2.  * 獲取但不移除此隊列的頭;若是此隊列爲空,則返回 null 
  3.  */  
  4. public E peek() {  
  5.     final ReentrantLock lock = this.lock;  
  6.     //獲取鎖  
  7.     lock.lock();  
  8.     try {  
  9.         //判斷隊列中是否有元素,若是沒有則返回null,若是存在則返回該元素  
  10.         return (count == 0) ? null : items[takeIndex];  
  11.     } finally {  
  12.         //釋放鎖  
  13.         lock.unlock();  
  14.     }  
  15. }  

 

        peek代碼比較簡單,首先判斷隊列是否有元素,即count==0,若是爲空則返回null,非空則返回相應元素。

        2)poll方法

        獲取並移除此隊列的頭,若是此隊列爲空,則返回 null。如下是poll方法的源代碼:

Java代碼   收藏代碼
  1. /** 
  2.  * 獲取並移除此隊列的頭,若是此隊列爲空,則返回 null 
  3.  */  
  4. public E poll() {  
  5.     final ReentrantLock lock = this.lock;  
  6.     //獲取鎖  
  7.     lock.lock();  
  8.     try {  
  9.         //判斷是否存在元素  
  10.         if (count == 0)  
  11.             return null;  
  12.         //調用extract方法返回元素  
  13.         E x = extract();  
  14.         return x;  
  15.     } finally {  
  16.         //釋放鎖  
  17.         lock.unlock();  
  18.     }  
  19. }  

        poll方法調用的是 extract()方法來獲取頭元素。

        3)extract方法

        如下是extract()方法的源代碼:

Java代碼   收藏代碼
  1. /** 
  2.  * 從 takeIndex位置獲取元素(在得到鎖的狀況下調用) 
  3.  */  
  4. private E extract() {  
  5.     final E[] items = this.items;  
  6.     //獲取元素  
  7.     E x = items[takeIndex];  
  8.     //移除原位置元素  
  9.     items[takeIndex] = null;  
  10.     //計算 takeIndex新值  
  11.     takeIndex = inc(takeIndex);  
  12.     --count;  
  13.     //喚醒添加線程  
  14.     notFull.signal();  
  15.     return x;  
  16. }  

        4)take方法

        獲取並移除此隊列的頭部,在元素變得可用以前一直等待(若是有必要)。

Java代碼   收藏代碼
  1. /** 
  2.  * 獲取並移除此隊列的頭部,在元素變得可用以前一直等待(若是有必要) 
  3.  */  
  4. public E take() throws InterruptedException {  
  5.     final ReentrantLock lock = this.lock;  
  6.     // 獲取中斷鎖  
  7.     lock.lockInterruptibly();  
  8.     try {  
  9.         try {  
  10.             // 若是隊列未空則阻塞等待,直到有元素爲止  
  11.             while (count == 0)  
  12.                 notEmpty.await();  
  13.         } catch (InterruptedException ie) {  
  14.             notEmpty.signal(); // 喚醒獲取線程  
  15.             throw ie;  
  16.         }  
  17.         // 調用extract方法返回元素  
  18.         E x = extract();  
  19.         return x;  
  20.     } finally {  
  21.         // 釋放鎖  
  22.         lock.unlock();  
  23.     }  
  24. }  

        與put方法相似,take方法也是利用循環阻塞的方式來獲取元素,若是沒有元素則等待,直至獲取元素爲止。

        與put方法的例子相似,生產者只生產5個產品,消費完這5個產品後,消費者就不得不等待隊列有元素可取:

Java代碼   收藏代碼
  1. class Producer implements Runnable {  
  2.     private final ArrayBlockingQueue<Integer> queue;  
  3.     private int i;  
  4.   
  5.     Producer(ArrayBlockingQueue<Integer> q) {  
  6.         queue = q;  
  7.     }  
  8.   
  9.     public void run() {  
  10.         try {  
  11.             for (int i = 0; i < 5; i++) {  
  12.                 int p = produce();  
  13.                 queue.put(p);// 將產品放入緩衝隊列  
  14.                 System.out.println("插入成功:" + p);  
  15.             }  
  16.         } catch (InterruptedException e) {  
  17.             e.printStackTrace();  
  18.         }  
  19.     }  
  20.   
  21.     int produce() {  
  22.         return i++;// 生產產品  
  23.     }  
  24. }  
  25.   
  26. class Consumer implements Runnable {  
  27.     private final ArrayBlockingQueue<Integer> queue;  
  28.   
  29.     Consumer(ArrayBlockingQueue<Integer> q) {  
  30.         queue = q;  
  31.     }  
  32.   
  33.     public void run() {  
  34.         try {  
  35.             while (true) {  
  36.                 int p = queue.take();  
  37.                 System.out.println("獲取成功:" + p);  
  38.             }  
  39.         } catch (InterruptedException e) {  
  40.             e.printStackTrace();  
  41.         }  
  42.     }  
  43.   
  44.     void consume(Object x) {  
  45.         System.out.println("消費:" + x);// 消費產品  
  46.     }  
  47. }  
  48.   
  49. public class Runner {  
  50.     public static void main(String[] args) {  
  51.         ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(10);// 或其餘實現  
  52.         Producer p = new Producer(q);  
  53.         Consumer c1 = new Consumer(q);  
  54.         Consumer c2 = new Consumer(q);  
  55.         new Thread(p).start();  
  56.         new Thread(c1).start();  
  57.         new Thread(c2).start();  
  58.     }  
  59. }  
  60. //結果:  
  61. 插入成功:0  
  62. 插入成功:1  
  63. 插入成功:2  
  64. 插入成功:3  
  65. 插入成功:4  
  66. 獲取成功:0  
  67. 獲取成功:1  
  68. 獲取成功:2  
  69. 獲取成功:3  
  70. 獲取成功:4  

        以後程序也是會阻塞在那裏。

 

        5.移除元素

        1)remove方法

        remove方法今後隊列中移除指定元素的單個實例(若是存在)。更確切地講,若是此隊列包含一個或多個知足 o.equals(e) 的元素 e,則移除該元素。若是此隊列包含指定的元素(或者此隊列因爲調用而發生更改),則返回 true。 

Java代碼   收藏代碼
  1. /** 
  2.  * 今後隊列中移除指定元素的單個實例(若是存在) 
  3.  */  
  4. public boolean remove(Object o) {  
  5.     //判斷要移除元素是否爲空  
  6.     if (o == null)  
  7.         return false;  
  8.     final E[] items = this.items;  
  9.     final ReentrantLock lock = this.lock;  
  10.     //獲取鎖  
  11.     lock.lock();  
  12.     try {  
  13.         int i = takeIndex;  
  14.         int k = 0;  
  15.         for (;;) {  
  16.             //判斷隊列是否含有元素  
  17.             if (k++ >= count)  
  18.                 return false;  
  19.             //比較  
  20.             if (o.equals(items[i])) {  
  21.                 //移除  
  22.                 removeAt(i);  
  23.                 return true;  
  24.             }  
  25.             //返回i新值,以便下次循環使用  
  26.             i = inc(i);  
  27.         }  
  28.   
  29.     } finally {  
  30.         //釋放鎖  
  31.         lock.unlock();  
  32.     }  
  33. }  

        remove方法其中利用循環來不斷判斷該元素的位置,若是找到則調用 removeAt方法移除指定位置的數組元素。

        如下是一個移除的小例子:

Java代碼   收藏代碼
  1. ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(10);  
  2. // 添加10個元素  
  3. for (int i = 0; i < 10; i++) {  
  4.     q.add(i);  
  5. }  
  6. // 移除值爲 1,3,5,7,9 的這五個元素  
  7. q.remove(1);  
  8. q.remove(3);  
  9. q.remove(5);  
  10. q.remove(7);  
  11. q.remove(9);  
  12. //又移除了一次 9  
  13. q.remove(9);  
  14. for (Integer i : q) {  
  15.     System.out.println(i);  
  16. }  
  17. //結果:  
  18. 0  
  19. 2  
  20. 4  
  21. 6  
  22. 8  

        從結果能夠看出,從隊列中正確的移除了咱們指定的元素,在最後即便指定已經不存在的元素值,remove方法也以後返回false。

        2)drainTo方法

        drainTo方法用於移除此隊列中全部可用的元素,並將它們添加到給定 collection 中。此操做可能比反覆輪詢此隊列更有效。在試圖向 collection c 中添加元素沒有成功時,可能致使在拋出相關異常時,元素會同時在兩個 collection 中出現,或者在其中一個 collection 中出現,也可能在兩個 collection 中都不出現。若是試圖將一個隊列放入自身隊列中,則會致使 IllegalArgumentException 異常。此外,若是正在進行此操做時修改指定的 collection,則此操做行爲是不肯定的。 

        如下是 drainTo方法的源代碼:

Java代碼   收藏代碼
  1. public int drainTo(Collection<? super E> c) {  
  2.     //若是指定 collection爲 null 拋出異常  
  3.     if (c == null)  
  4.         throw new NullPointerException();  
  5.     //若是指定 collection 是此隊列,或者此隊列元素的某些屬性不容許將其添加到指定 collection 拋出異常  
  6.     if (c == this)  
  7.         throw new IllegalArgumentException();  
  8.     final E[] items = this.items;  
  9.     final ReentrantLock lock = this.lock;  
  10.     //獲取鎖  
  11.     lock.lock();  
  12.     try {  
  13.         //take操做的位置  
  14.         int i = takeIndex;  
  15.         int n = 0;  
  16.         //元素數量  
  17.         int max = count;  
  18.         //利用循環不斷取出元素添加到c中  
  19.         while (n < max) {  
  20.             c.add(items[i]);  
  21.             items[i] = null;  
  22.             i = inc(i);  
  23.             ++n;  
  24.         }  
  25.         //添加完成後初始化必要值,喚醒添加線程  
  26.         if (n > 0) {  
  27.             count = 0;  
  28.             putIndex = 0;  
  29.             takeIndex = 0;  
  30.             notFull.signalAll();  
  31.         }  
  32.         //返回添加元素數量  
  33.         return n;  
  34.     } finally {  
  35.         //釋放鎖  
  36.         lock.unlock();  
  37.     }  
  38. }  

        代碼中並無添加失敗的相關處理,因此結果如上所說並不必定完整。如下是相關實例:

Java代碼   收藏代碼
  1. ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(10);  
  2. List<Integer> list = new ArrayList<Integer>();  
  3. // 添加10個元素  
  4. for (int i = 0; i < 10; i++) {  
  5.     q.add(i);  
  6.     list.add(i + 10);  
  7. }  
  8. //將q中的元素添加到 list中  
  9. q.drainTo(list);  
  10. for (Integer i : list) {  
  11.     System.out.println(i);  
  12. }  
  13. //結果:  
  14. 10  
  15. 11  
  16. 12  
  17. 13  
  18. 14  
  19. 15  
  20. 16  
  21. 17  
  22. 18  
  23. 19  
  24. 0  
  25. 1  
  26. 2  
  27. 3  
  28. 4  
  29. 5  
  30. 6  
  31. 7  
  32. 8  
  33. 9  

        須要值得注意的是 drainTo方法是將隊列中的元素按順序添加到指定 Collection中,別弄反了。

        drainTo(Collection<? super E> c, int maxElements)用法相似,只不過指定了移除元素數。

        3)clear方法

        移除此隊列中的全部元素。在此調用返回以後,隊列將爲空。

Java代碼   收藏代碼
  1. /** 
  2.  * 移除此隊列中的全部元素。在此調用返回以後,隊列將爲空 
  3.  */  
  4. public void clear() {  
  5.     final E[] items = this.items;  
  6.     final ReentrantLock lock = this.lock;  
  7.     //獲取鎖  
  8.     lock.lock();  
  9.     try {  
  10.         int i = takeIndex;  
  11.         int k = count;  
  12.         //將數組元素置爲null  
  13.         while (k-- > 0) {  
  14.             items[i] = null;  
  15.             i = inc(i);  
  16.         }  
  17.         //初始化其餘參數  
  18.         count = 0;  
  19.         putIndex = 0;  
  20.         takeIndex = 0;  
  21.         //喚醒添加線程  
  22.         notFull.signalAll();  
  23.     } finally {  
  24.         //釋放鎖  
  25.         lock.unlock();  
  26.     }  
  27. }  

        clear方法比較簡單,就是利用循環清除數組中的元素,而後將相關參數置爲初始值。

        ArrayBlockingQueue還有一些其餘方法,這些方法相對簡單這裏就不細說了。

相關文章
相關標籤/搜索