ArrayBlockingQueue源代码及解析

一些解析:

ArrayBlockingQueue用的锁一个Reentrantlock,而下面的两个notEmptyCondition和notFullCondition是通过Reentrantlock的newCondition()方法得到的。

/*** Main lock guarding all access */
072     private final ReentrantLock lock;
073     /*** Condition for waiting takes */
074     private final ConditionnotEmpty;
075     /*** Condition for waiting puts */
076     private final ConditionnotFull;

对于时间控制上即offer和poll都有阻塞的timeout时间控制,timeout时间控制是一个非常常用的功能,这里用的Condition的awaitNanos()方法,注意这个方法是阻塞性质的。

对于Offer的实现,大致思路是这样的,首先获取lock,然后由for循环控制进行插入,插入时首先判断是否已满,如果满了就进行awaitNanos方法进行阻塞等待直到插入成功或者超时。

public boolean offer(E e, long timeout, TimeUnit unit)
271         throws InterruptedException {
272  
273         if (e == nullthrow new NullPointerException();
274         long nanos = unit.toNanos(timeout);
275         final ReentrantLock lock = this.lock;
276         lock.lockInterruptibly();
277         try {
278             for (;;) {
279                 if (count != items.length) {
280                     insert(e);
281                     return true;
282                 }
283                 if (nanos <= 0)
284                     return false;
285                 try {
286                     nanos = notFull.awaitNanos(nanos);
287                 catch (InterruptedException ie) {
288                     notFull.signal(); // propagate to non-interrupted thread
289                     throw ie;
290                 }
291             }
292         finally {
293             lock.unlock();
294         }
295     }
296  
另外关于上面这段代码中使用了ReentrantLock的lockInterruptibly()方法来表示此Lock可以被interupt

If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of two things happens:

  • The lock is acquired by the current thread; or
  • Some other thread interrupts the current thread.

If the lock is acquired by the current thread then the lock hold count is set to one.

If the current thread:

  • has its interrupted status set on entry to this method; or
  • is interrupted while acquiring the lock,
then  InterruptedException  is thrown and the current thread's interrupted status is cleared.


提到关于时间控制,如果不能使用Reentrantlock及Condition的方式,还有其他什么方式么?如下这个使用Executor和FutureTask来进行时间控制,即通过使用将需要由时间控制的东东放到一个线程由executor执行,然后使用FutureTask的get方法来进行超时控制,如果超时了,就抛出一个timeoutException异常,也非常的好

[java]  view plain copy
  1. public boolean judgeMasters(final String hostName,final String accoutName){  
  2.        
  3.      ExecutorService executor = Executors.newSingleThreadExecutor();    
  4.      FutureTask<Boolean> fuTask=new FutureTask<Boolean>(new Callable<Boolean>(){  
  5.         @Override  
  6.         public Boolean call() throws Exception {  
  7.             return exeCmd(hostName,accoutName);  
  8.         }  
  9.      });  
  10.      try {  
  11.         executor.execute(fuTask);  
  12.         return<span style="background-color: rgb(255, 102, 0);"> fuTask.get(5, TimeUnit.SECONDS);</span>  
  13.     } catch (InterruptedException e) {  
  14.         e.printStackTrace();  
  15.         return false;  
  16.     } catch (ExecutionException e) {  
  17.         e.printStackTrace();  
  18.         return false;  
  19.     } catch (TimeoutException e) {  
  20.         e.printStackTrace();  
  21.         return false;  
  22.     }  
  23.  }  

关于Condition的官方说明,简单的说Condition的wait和singal方法就是为了替代原来的wait和notify,就像ReentrantLock或其他lock就像为了替换原来的synchronized关键字,并且像wait和notify的使用必须要被synchronized围绕,而condition也要被获得的lock围绕

Condition factors out the Object monitor methods (wait,notify andnotifyAll) into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitraryLock implementations. Where aLock replaces the use ofsynchronized methods and statements, aCondition replaces the use of the Object monitor methods.  

Conditions (also known as condition queues or condition variables) provide a means for one thread to suspend execution (to "wait") until notified by another thread that some state condition may now be true. Because access to this shared state information occurs in different threads, it must be protected, so a lock of some form is associated with the condition. The key property that waiting for a condition provides is that itatomically releases the associated lock and suspends the current thread, just likeObject.wait

Condition instance is intrinsically bound to a lock. To obtain aCondition instance for a particularLock instance use itsnewCondition() method. 

Note that Condition instances are just normal objects and can themselves be used as the target in asynchronized statement, and can have their own monitorwait andnotificationmethods invoked. Acquiring the monitor lock of aCondition instance, or using its monitor methods, has no specified relationship with acquiring theLock associated with thatCondition or the use of its waiting andsignalling methods. It is recommended that to avoid confusion you never useCondition instances in this way, except perhaps within their own implementation.


ArrayBlockingQueue源代码赏析:

[java]  view plain copy
  1. /** 
  2.  * Written by Doug Lea with assistance from members of JCP JSR-166 
  3.  * Expert Group and released to the public domain, as explained at 
  4.  * http://creativecommons.org/licenses/publicdomain 
  5.  */  
  6.   
  7. package java.util.concurrent;  
  8. import java.util.concurrent.locks.*;  
  9. import java.util.*;  
  10.   
  11. // BEGIN android-note  
  12. // removed link to collections framework docs  
  13. // END android-note  
  14.   
  15. /*** 
  16.  * A bounded {@linkplain BlockingQueue blocking queue} backed by an 
  17.  * array.  This queue orders elements FIFO (first-in-first-out).  The 
  18.  * <em>head</em> of the queue is that element that has been on the 
  19.  * queue the longest time.  The <em>tail</em> of the queue is that 
  20.  * element that has been on the queue the shortest time. New elements 
  21.  * are inserted at the tail of the queue, and the queue retrieval 
  22.  * operations obtain elements at the head of the queue. 
  23.  * 
  24.  * <p>This is a classic "bounded buffer", in which a 
  25.  * fixed-sized array holds elements inserted by producers and 
  26.  * extracted by consumers.  Once created, the capacity cannot be 
  27.  * increased.  Attempts to <tt>put</tt> an element into a full queue 
  28.  * will result in the operation blocking; attempts to <tt>take</tt> an 
  29.  * element from an empty queue will similarly block. 
  30.  * 
  31.  * <p> This class supports an optional fairness policy for ordering 
  32.  * waiting producer and consumer threads.  By default, this ordering 
  33.  * is not guaranteed. However, a queue constructed with fairness set 
  34.  * to <tt>true</tt> grants threads access in FIFO order. Fairness 
  35.  * generally decreases throughput but reduces variability and avoids 
  36.  * starvation. 
  37.  * 
  38.  * <p>This class and its iterator implement all of the 
  39.  * <em>optional</em> methods of the {@link Collection} and {@link 
  40.  * Iterator} interfaces. 
  41.  * 
  42.  * @since 1.5 
  43.  * @author Doug Lea 
  44.  * @param <E> the type of elements held in this collection 
  45.  */  
  46. public class ArrayBlockingQueue<E> extends AbstractQueue<E>  
  47.         implements BlockingQueue<E>, java.io.Serializable {  
  48.   
  49.     /*** 
  50.      * Serialization ID. This class relies on default serialization 
  51.      * even for the items array, which is default-serialized, even if 
  52.      * it is empty. Otherwise it could not be declared final, which is 
  53.      * necessary here. 
  54.      */  
  55.     private static final long serialVersionUID = -817911632652898426L;  
  56.   
  57.     /*** The queued items  */  
  58.     private final E[] items;  
  59.     /*** items index for next take, poll or remove */  
  60.     private int takeIndex;  
  61.     /*** items index for next put, offer, or add. */  
  62.     private int putIndex;  
  63.     /*** Number of items in the queue */  
  64.     private int count;  
  65.   
  66.     /** 
  67.      * Concurrency control uses the classic two-condition algorithm 
  68.      * found in any textbook. 
  69.      */  
  70.   
  71.     /*** Main lock guarding all access */  
  72.     private final ReentrantLock lock;  
  73.     /*** Condition for waiting takes */  
  74.     private final Condition notEmpty;  
  75.     /*** Condition for waiting puts */  
  76.     private final Condition notFull;  
  77.   
  78.     // Internal helper methods  
  79.   
  80.     /*** 
  81.      * Circularly increment i. 
  82.      */  
  83.     final int inc(int i) {  
  84.         return (++i == items.length)? 0 : i;  
  85.     }  
  86.   
  87.     /*** 
  88.      * Inserts element at current put position, advances, and signals. 
  89.      * Call only when holding lock. 
  90.      */  
  91.     private void insert(E x) {  
  92.         items[putIndex] = x;  
  93.         putIndex = inc(putIndex);  
  94.         ++count;  
  95.         notEmpty.signal();  
  96.     }  
  97.   
  98.     /*** 
  99.      * Extracts element at current take position, advances, and signals. 
  100.      * Call only when holding lock. 
  101.      */  
  102.     private E extract() {  
  103.         final E[] items = this.items;  
  104.         E x = items[takeIndex];  
  105.         items[takeIndex] = null;  
  106.         takeIndex = inc(takeIndex);  
  107.         --count;  
  108.         notFull.signal();  
  109.         return x;  
  110.     }  
  111.   
  112.     /*** 
  113.      * Utility for remove and iterator.remove: Delete item at position i. 
  114.      * Call only when holding lock. 
  115.      */  
  116.     void removeAt(int i) {  
  117.         final E[] items = this.items;  
  118.         // if removing front item, just advance  
  119.         if (i == takeIndex) {  
  120.             items[takeIndex] = null;  
  121.             takeIndex = inc(takeIndex);  
  122.         } else {  
  123.             // slide over all others up through putIndex.  
  124.             for (;;) {  
  125.                 int nexti = inc(i);  
  126.                 if (nexti != putIndex) {  
  127.                     items[i] = items[nexti];  
  128.                     i = nexti;  
  129.                 } else {  
  130.                     items[i] = null;  
  131.                     putIndex = i;  
  132.                     break;  
  133.                 }  
  134.             }  
  135.         }  
  136.         --count;  
  137.         notFull.signal();  
  138.     }  
  139.   
  140.     /*** 
  141.      * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed) 
  142.      * capacity and default access policy. 
  143.      * 
  144.      * @param capacity the capacity of this queue 
  145.      * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1 
  146.      */  
  147.     public ArrayBlockingQueue(int capacity) {  
  148.         this(capacity, false);  
  149.     }  
  150.   
  151.     /*** 
  152.      * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed) 
  153.      * capacity and the specified access policy. 
  154.      * 
  155.      * @param capacity the capacity of this queue 
  156.      * @param fair if <tt>true</tt> then queue accesses for threads blocked 
  157.      *        on insertion or removal, are processed in FIFO order; 
  158.      *        if <tt>false</tt> the access order is unspecified. 
  159.      * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1 
  160.      */  
  161.     public ArrayBlockingQueue(int capacity, boolean fair) {  
  162.         if (capacity <= 0)  
  163.             throw new IllegalArgumentException();  
  164.         this.items = (E[]) new Object[capacity];  
  165.         lock = new ReentrantLock(fair);  
  166.         notEmpty = lock.newCondition();  
  167.         notFull =  lock.newCondition();  
  168.     }  
  169.   
  170.     /*** 
  171.      * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed) 
  172.      * capacity, the specified access policy and initially containing the 
  173.      * elements of the given collection, 
  174.      * added in traversal order of the collection's iterator. 
  175.      * 
  176.      * @param capacity the capacity of this queue 
  177.      * @param fair if <tt>true</tt> then queue accesses for threads blocked 
  178.      *        on insertion or removal, are processed in FIFO order; 
  179.      *        if <tt>false</tt> the access order is unspecified. 
  180.      * @param c the collection of elements to initially contain 
  181.      * @throws IllegalArgumentException if <tt>capacity</tt> is less than 
  182.      *         <tt>c.size()</tt>, or less than 1. 
  183.      * @throws NullPointerException if the specified collection or any 
  184.      *         of its elements are null 
  185.      */  
  186.     public ArrayBlockingQueue(int capacity, boolean fair,  
  187.                               Collection<? extends E> c) {  
  188.         this(capacity, fair);  
  189.         if (capacity < c.size())  
  190.             throw new IllegalArgumentException();  
  191.   
  192.         for (Iterator<? extends E> it = c.iterator(); it.hasNext();)  
  193.             add(it.next());  
  194.     }  
  195.   
  196.     /*** 
  197.      * Inserts the specified element at the tail of this queue if it is 
  198.      * possible to do so immediately without exceeding the queue's capacity, 
  199.      * returning <tt>true</tt> upon success and throwing an 
  200.      * <tt>IllegalStateException</tt> if this queue is full. 
  201.      * 
  202.      * @param e the element to add 
  203.      * @return <tt>true</tt> (as specified by {@link Collection#add}) 
  204.      * @throws IllegalStateException if this queue is full 
  205.      * @throws NullPointerException if the specified element is null 
  206.      */  
  207.     public boolean add(E e) {  
  208.         return super.add(e);  
  209.     }  
  210.   
  211.     /*** 
  212.      * Inserts the specified element at the tail of this queue if it is 
  213.      * possible to do so immediately without exceeding the queue's capacity, 
  214.      * returning <tt>true</tt> upon success and <tt>false</tt> if this queue 
  215.      * is full.  This method is generally preferable to method {@link #add}, 
  216.      * which can fail to insert an element only by throwing an exception. 
  217.      * 
  218.      * @throws NullPointerException if the specified element is null 
  219.      */  
  220.     public boolean offer(E e) {  
  221.         if (e == nullthrow new NullPointerException();  
  222.         final ReentrantLock lock = this.lock;  
  223.         lock.lock();  
  224.         try {  
  225.             if (count == items.length)  
  226.                 return false;  
  227.             else {  
  228.                 insert(e);  
  229.                 return true;  
  230.             }  
  231.         } finally {  
  232.             lock.unlock();  
  233.         }  
  234.     }  
  235.   
  236.     /*** 
  237.      * Inserts the specified element at the tail of this queue, waiting 
  238.      * for space to become available if the queue is full. 
  239.      * 
  240.      * @throws InterruptedException {@inheritDoc} 
  241.      * @throws NullPointerException {@inheritDoc} 
  242.      */  
  243.     public void put(E e) throws InterruptedException {  
  244.         if (e == nullthrow new NullPointerException();  
  245.         final E[] items = this.items;  
  246.         final ReentrantLock lock = this.lock;  
  247.         lock.lockInterruptibly();  
  248.         try {  
  249.             try {  
  250.                 while (count == items.length)  
  251.                     notFull.await();  
  252.             } catch (InterruptedException ie) {  
  253.                 notFull.signal(); // propagate to non-interrupted thread  
  254.                 throw ie;  
  255.             }  
  256.             insert(e);  
  257.         } finally {  
  258.             lock.unlock();  
  259.         }  
  260.     }  
  261.   
  262.     /*** 
  263.      * Inserts the specified element at the tail of this queue, waiting 
  264.      * up to the specified wait time for space to become available if 
  265.      * the queue is full. 
  266.      * 
  267.      * @throws InterruptedException {@inheritDoc} 
  268.      * @throws NullPointerException {@inheritDoc} 
  269.      */  
  270.     public boolean offer(E e, long timeout, TimeUnit unit)  
  271.         throws InterruptedException {  
  272.   
  273.         if (e == nullthrow new NullPointerException();  
  274.         long nanos = unit.toNanos(timeout);  
  275.         final ReentrantLock lock = this.lock;  
  276.         lock.lockInterruptibly();  
  277.         try {  
  278.             for (;;) {  
  279.                 if (count != items.length) {  
  280.                     insert(e);  
  281.                     return true;  
  282.                 }  
  283.                 if (nanos <= 0)  
  284.                     return false;  
  285.                 try {  
  286.                     nanos = notFull.awaitNanos(nanos);  
  287.                 } catch (InterruptedException ie) {  
  288.                     notFull.signal(); // propagate to non-interrupted thread  
  289.                     throw ie;  
  290.                 }  
  291.             }  
  292.         } finally {  
  293.             lock.unlock();  
  294.         }  
  295.     }  
  296.   
  297.     public E poll() {  
  298.         final ReentrantLock lock = this.lock;  
  299.         lock.lock();  
  300.         try {  
  301.             if (count == 0)  
  302.                 return null;  
  303.             E x = extract();  
  304.             return x;  
  305.         } finally {  
  306.             lock.unlock();  
  307.         }  
  308.     }  
  309.   
  310.     public E take() throws InterruptedException {  
  311.         final ReentrantLock lock = this.lock;  
  312.         lock.lockInterruptibly();  
  313.         try {  
  314.             try {  
  315.                 while (count == 0)  
  316.                     notEmpty.await();  
  317.             } catch (InterruptedException ie) {  
  318.                 notEmpty.signal(); // propagate to non-interrupted thread  
  319.                 throw ie;  
  320.             }  
  321.             E x = extract();  
  322.             return x;  
  323.         } finally {  
  324.             lock.unlock();  
  325.         }  
  326.     }  
  327.   
  328.     public E poll(long timeout, TimeUnit unit) throws InterruptedException {  
  329.         long nanos = unit.toNanos(timeout);  
  330.         final ReentrantLock lock = this.lock;  
  331.         lock.lockInterruptibly();  
  332.         try {  
  333.             for (;;) {  
  334.                 if (count != 0) {  
  335.                     E x = extract();  
  336.                     return x;  
  337.                 }  
  338.                 if (nanos <= 0)  
  339.                     return null;  
  340.                 try {  
  341.                     nanos = notEmpty.awaitNanos(nanos);  
  342.                 } catch (InterruptedException ie) {  
  343.                     notEmpty.signal(); // propagate to non-interrupted thread  
  344.                     throw ie;  
  345.                 }  
  346.   
  347.             }  
  348.         } finally {  
  349.             lock.unlock();  
  350.         }  
  351.     }  
  352.   
  353.     public E peek() {  
  354.         final ReentrantLock lock = this.lock;  
  355.         lock.lock();  
  356.         try {  
  357.             return (count == 0) ? null : items[takeIndex];  
  358.         } finally {  
  359.             lock.unlock();  
  360.         }  
  361.     }  
  362.   
  363.     // this doc comment is overridden to remove the reference to collections  
  364.     // greater in size than Integer.MAX_VALUE  
  365.     /*** 
  366.      * Returns the number of elements in this queue. 
  367.      * 
  368.      * @return the number of elements in this queue 
  369.      */  
  370.     public int size() {  
  371.         final ReentrantLock lock = this.lock;  
  372.         lock.lock();  
  373.         try {  
  374.             return count;  
  375.         } finally {  
  376.             lock.unlock();  
  377.         }  
  378.     }  
  379.   
  380.     // this doc comment is a modified copy of the inherited doc comment,  
  381.     // without the reference to unlimited queues.  
  382.     /*** 
  383.      * Returns the number of additional elements that this queue can ideally 
  384.      * (in the absence of memory or resource constraints) accept without 
  385.      * blocking. This is always equal to the initial capacity of this queue 
  386.      * less the current <tt>size</tt> of this queue. 
  387.      * 
  388.      * <p>Note that you <em>cannot</em> always tell if an attempt to insert 
  389.      * an element will succeed by inspecting <tt>remainingCapacity</tt> 
  390.      * because it may be the case that another thread is about to 
  391.      * insert or remove an element. 
  392.      */  
  393.     public int remainingCapacity() {  
  394.         final ReentrantLock lock = this.lock;  
  395.         lock.lock();  
  396.         try {  
  397.             return items.length - count;  
  398.         } finally {  
  399.             lock.unlock();  
  400.         }  
  401.     }  
  402.   
  403.     /*** 
  404.      * Removes a single instance of the specified element from this queue, 
  405.      * if it is present.  More formally, removes an element <tt>e</tt> such 
  406.      * that <tt>o.equals(e)</tt>, if this queue contains one or more such 
  407.      * elements. 
  408.      * Returns <tt>true</tt> if this queue contained the specified element 
  409.      * (or equivalently, if this queue changed as a result of the call). 
  410.      * 
  411.      * @param o element to be removed from this queue, if present 
  412.      * @return <tt>true</tt> if this queue changed as a result of the call 
  413.      */  
  414.     public boolean remove(Object o) {  
  415.         if (o == nullreturn false;  
  416.         final E[] items = this.items;  
  417.         final ReentrantLock lock = this.lock;  
  418.         lock.lock();  
  419.         try {  
  420.             int i = takeIndex;  
  421.             int k = 0;  
  422.             for (;;) {  
  423.                 if (k++ >= count)  
  424.                     return false;  
  425.                 if (o.equals(items[i])) {  
  426.                     removeAt(i);  
  427.                     return true;  
  428.                 }  
  429.                 i = inc(i);  
  430.             }  
  431.   
  432.         } finally {  
  433.             lock.unlock();  
  434.         }  
  435.     }  
  436.   
  437.     /*** 
  438.      * Returns <tt>true</tt> if this queue contains the specified element. 
  439.      * More formally, returns <tt>true</tt> if and only if this queue contains 
  440.      * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>. 
  441.      * 
  442.      * @param o object to be checked for containment in this queue 
  443.      * @return <tt>true</tt> if this queue contains the specified element 
  444.      */  
  445.     public boolean contains(Object o) {  
  446.         if (o == nullreturn false;  
  447.         final E[] items = this.items;  
  448.         final ReentrantLock lock = this.lock;  
  449.         lock.lock();  
  450.         try {  
  451.             int i = takeIndex;  
  452.             int k = 0;  
  453.             while (k++ < count) {  
  454.                 if (o.equals(items[i]))  
  455.                     return true;  
  456.                 i = inc(i);  
  457.             }  
  458.             return false;  
  459.         } finally {  
  460.             lock.unlock();  
  461.         }  
  462.     }  
  463.   
  464.     /*** 
  465.      * Returns an array containing all of the elements in this queue, in 
  466.      * proper sequence. 
  467.      * 
  468.      * <p>The returned array will be "safe" in that no references to it are 
  469.      * maintained by this queue.  (In other words, this method must allocate 
  470.      * a new array).  The caller is thus free to modify the returned array. 
  471.      * 
  472.      * <p>This method acts as bridge between array-based and collection-based 
  473.      * APIs. 
  474.      * 
  475.      * @return an array containing all of the elements in this queue 
  476.      */  
  477.     public Object[] toArray() {  
  478.         final E[] items = this.items;  
  479.         final ReentrantLock lock = this.lock;  
  480.         lock.lock();  
  481.         try {  
  482.             Object[] a = new Object[count];  
  483.             int k = 0;  
  484.             int i = takeIndex;  
  485.             while (k < count) {  
  486.                 a[k++] = items[i];  
  487.                 i = inc(i);  
  488.             }  
  489.             return a;  
  490.         } finally {  
  491.             lock.unlock();  
  492.         }  
  493.     }  
  494.   
  495.     /*** 
  496.      * Returns an array containing all of the elements in this queue, in 
  497.      * proper sequence; the runtime type of the returned array is that of 
  498.      * the specified array.  If the queue fits in the specified array, it 
  499.      * is returned therein.  Otherwise, a new array is allocated with the 
  500.      * runtime type of the specified array and the size of this queue. 
  501.      * 
  502.      * <p>If this queue fits in the specified array with room to spare 
  503.      * (i.e., the array has more elements than this queue), the element in 
  504.      * the array immediately following the end of the queue is set to 
  505.      * <tt>null</tt>. 
  506.      * 
  507.      * <p>Like the {@link #toArray()} method, this method acts as bridge between 
  508.      * array-based and collection-based APIs.  Further, this method allows 
  509.      * precise control over the runtime type of the output array, and may, 
  510.      * under certain circumstances, be used to save allocation costs. 
  511.      * 
  512.      * <p>Suppose <tt>x</tt> is a queue known to contain only strings. 
  513.      * The following code can be used to dump the queue into a newly 
  514.      * allocated array of <tt>String</tt>: 
  515.      * 
  516.      * <pre> 
  517.      *     String[] y = x.toArray(new String[0]);</pre> 
  518.      * 
  519.      * Note that <tt>toArray(new Object[0])</tt> is identical in function to 
  520.      * <tt>toArray()</tt>. 
  521.      * 
  522.      * @param a the array into which the elements of the queue are to 
  523.      *          be stored, if it is big enough; otherwise, a new array of the 
  524.      *          same runtime type is allocated for this purpose 
  525.      * @return an array containing all of the elements in this queue 
  526.      * @throws ArrayStoreException if the runtime type of the specified array 
  527.      *         is not a supertype of the runtime type of every element in 
  528.      *         this queue 
  529.      * @throws NullPointerException if the specified array is null 
  530.      */  
  531.     public <T> T[] toArray(T[] a) {  
  532.         final E[] items = this.items;  
  533.         final ReentrantLock lock = this.lock;  
  534.         lock.lock();  
  535.         try {  
  536.             if (a.length < count)  
  537.                 a = (T[])java.lang.reflect.Array.newInstance(  
  538.                     a.getClass().getComponentType(),  
  539.                     count  
  540.                     );  
  541.   
  542.             int k = 0;  
  543.             int i = takeIndex;  
  544.             while (k < count) {  
  545.                 a[k++] = (T)items[i];  
  546.                 i = inc(i);  
  547.             }  
  548.             if (a.length > count)  
  549.                 a[count] = null;  
  550.             return a;  
  551.         } finally {  
  552.             lock.unlock();  
  553.         }  
  554.     }  
  555.   
  556.     public String toString() {  
  557.         final ReentrantLock lock = this.lock;  
  558.         lock.lock();  
  559.         try {  
  560.             return super.toString();  
  561.         } finally {  
  562.             lock.unlock();  
  563.         }  
  564.     }  
  565.   
  566.     /*** 
  567.      * Atomically removes all of the elements from this queue. 
  568.      * The queue will be empty after this call returns. 
  569.      */  
  570.     public void clear() {  
  571.         final E[] items = this.items;  
  572.         final ReentrantLock lock = this.lock;  
  573.         lock.lock();  
  574.         try {  
  575.             int i = takeIndex;  
  576.             int k = count;  
  577.             while (k-- > 0) {  
  578.                 items[i] = null;  
  579.                 i = inc(i);  
  580.             }  
  581.             count = 0;  
  582.             putIndex = 0;  
  583.             takeIndex = 0;  
  584.             notFull.signalAll();  
  585.         } finally {  
  586.             lock.unlock();  
  587.         }  
  588.     }  
  589.   
  590.     /*** 
  591.      * @throws UnsupportedOperationException {@inheritDoc} 
  592.      * @throws ClassCastException            {@inheritDoc} 
  593.      * @throws NullPointerException          {@inheritDoc} 
  594.      * @throws IllegalArgumentException      {@inheritDoc} 
  595.      */  
  596.     public int drainTo(Collection<? super E> c) {  
  597.         if (c == null)  
  598.             throw new NullPointerException();  
  599.         if (c == this)  
  600.             throw new IllegalArgumentException();  
  601.         final E[] items = this.items;  
  602.         final ReentrantLock lock = this.lock;  
  603.         lock.lock();  
  604.         try {  
  605.             int i = takeIndex;  
  606.             int n = 0;  
  607.             int max = count;  
  608.             while (n < max) {  
  609.                 c.add(items[i]);  
  610.                 items[i] = null;  
  611.                 i = inc(i);  
  612.                 ++n;  
  613.             }  
  614.             if (n > 0) {  
  615.                 count = 0;  
  616.                 putIndex = 0;  
  617.                 takeIndex = 0;  
  618.                 notFull.signalAll();  
  619.             }  
  620.             return n;  
  621.         } finally {  
  622.             lock.unlock();  
  623.         }  
  624.     }  
  625.   
  626.     /*** 
  627.      * @throws UnsupportedOperationException {@inheritDoc} 
  628.      * @throws ClassCastException            {@inheritDoc} 
  629.      * @throws NullPointerException          {@inheritDoc} 
  630.      * @throws IllegalArgumentException      {@inheritDoc} 
  631.      */  
  632.     public int drainTo(Collection<? super E> c, int maxElements) {  
  633.         if (c == null)  
  634.             throw new NullPointerException();  
  635.         if (c == this)  
  636.             throw new IllegalArgumentException();  
  637.         if (maxElements <= 0)  
  638.             return 0;  
  639.         final E[] items = this.items;  
  640.         final ReentrantLock lock = this.lock;  
  641.         lock.lock();  
  642.         try {  
  643.             int i = takeIndex;  
  644.             int n = 0;  
  645.             int sz = count;  
  646.             int max = (maxElements < count)? maxElements : count;  
  647.             while (n < max) {  
  648.                 c.add(items[i]);  
  649.                 items[i] = null;  
  650.                 i = inc(i);  
  651.                 ++n;  
  652.             }  
  653.             if (n > 0) {  
  654.                 count -= n;  
  655.                 takeIndex = i;  
  656.                 notFull.signalAll();  
  657.             }  
  658.             return n;  
  659.         } finally {  
  660.             lock.unlock();  
  661.         }  
  662.     }  
  663.   
  664.   
  665.     /*** 
  666.      * Returns an iterator over the elements in this queue in proper sequence. 
  667.      * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that 
  668.      * will never throw {@link ConcurrentModificationException}, 
  669.      * and guarantees to traverse elements as they existed upon 
  670.      * construction of the iterator, and may (but is not guaranteed to) 
  671.      * reflect any modifications subsequent to construction. 
  672.      * 
  673.      * @return an iterator over the elements in this queue in proper sequence 
  674.      */  
  675.     public Iterator<E> iterator() {  
  676.         final ReentrantLock lock = this.lock;  
  677.         lock.lock();  
  678.         try {  
  679.             return new Itr();  
  680.         } finally {  
  681.             lock.unlock();  
  682.         }  
  683.     }  
  684.   
  685.     /*** 
  686.      * Iterator for ArrayBlockingQueue 
  687.      */  
  688.     private class Itr implements Iterator<E> {  
  689.         /*** 
  690.          * Index of element to be returned by next, 
  691.          * or a negative number if no such. 
  692.          */  
  693.         private int nextIndex;  
  694.   
  695.         /*** 
  696.          * nextItem holds on to item fields because once we claim 
  697.          * that an element exists in hasNext(), we must return it in 
  698.          * the following next() call even if it was in the process of 
  699.          * being removed when hasNext() was called. 
  700.          */  
  701.         private E nextItem;  
  702.   
  703.         /*** 
  704.          * Index of element returned by most recent call to next. 
  705.          * Reset to -1 if this element is deleted by a call to remove. 
  706.          */  
  707.         private int lastRet;  
  708.   
  709.         Itr() {  
  710.             lastRet = -1;  
  711.             if (count == 0)  
  712.                 nextIndex = -1;  
  713.             else {  
  714.                 nextIndex = takeIndex;  
  715.                 nextItem = items[takeIndex];  
  716.             }  
  717.         }  
  718.   
  719.         public boolean hasNext() {  
  720.             /** 
  721.              * No sync. We can return true by mistake here 
  722.              * only if this iterator passed across threads, 
  723.              * which we don't support anyway. 
  724.              */  
  725.             return nextIndex >= 0;  
  726.         }  
  727.   
  728.         /*** 
  729.          * Checks whether nextIndex is valid; if so setting nextItem. 
  730.          * Stops iterator when either hits putIndex or sees null item. 
  731.          */  
  732.         private void checkNext() {  
  733.             if (nextIndex == putIndex) {  
  734.                 nextIndex = -1;  
  735.                 nextItem = null;  
  736.             } else {  
  737.                 nextItem = items[nextIndex];  
  738.                 if (nextItem == null)  
  739.                     nextIndex = -1;  
  740.             }  
  741.         }  
  742.   
  743.         public E next() {  
  744.             final ReentrantLock lock = ArrayBlockingQueue.this.lock;  
  745.             lock.lock();  
  746.             try {  
  747.                 if (nextIndex < 0)  
  748.                     throw new NoSuchElementException();  
  749.                 lastRet = nextIndex;  
  750.                 E x = nextItem;  
  751.                 nextIndex = inc(nextIndex);  
  752.                 checkNext();  
  753.                 return x;  
  754.             } finally {  
  755.                 lock.unlock();  
  756.             }  
  757.         }  
  758.   
  759.         public void remove() {  
  760.             final ReentrantLock lock = ArrayBlockingQueue.this.lock;  
  761.             lock.lock();  
  762.             try {  
  763.                 int i = lastRet;  
  764.                 if (i == -1)  
  765.                     throw new IllegalStateException();  
  766.                 lastRet = -1;  
  767.   
  768.                 int ti = takeIndex;  
  769.                 removeAt(i);  
  770.                 // back up cursor (reset to front if was first element)  
  771.                 nextIndex = (i == ti) ? takeIndex : i;  
  772.                 checkNext();  
  773.             } finally {  
  774.                 lock.unlock();  
  775.             }  
  776.         }  
  777.     }  
  778. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值