java1.7集合源码阅读:ArrayBlockingQueue

  ArrayBlockingQueue是一个先进先出线程安全的队列,队列头部是进入队列时间最长的元素,队尾是进入队列时间最短的元素,同时队列的最大容量是固定的。

先看类定义:

1 public class ArrayBlockingQueue<E> extends AbstractQueue<E>
2         implements BlockingQueue<E>, java.io.Serializable {
3       ......
4 }
ArrayBlockingQueue实现了BlockingQueue接口,是一个阻塞队列实现,内部通过数组进行数据存储:
1  /** The queued items */
2     final Object[] items;
3 
4     /** items index for next take, poll, peek or remove */
5     int takeIndex;
6 
7     /** items index for next put, offer, or add */
8     int putIndex;

对元素的增加操作,主要提供了三种使用场景:添加(队列已满则返回false)、限时等待添加,无限等待添加;

 1   /**
 2      * Inserts the specified element at the tail of this queue if it is
 3      * possible to do so immediately without exceeding the queue's capacity,
 4      * returning {@code true} upon success and throwing an
 5      * {@code IllegalStateException} if this queue is full.
 6      *
 7      * @param e the element to add
 8      * @return {@code true} (as specified by {@link Collection#add})
 9      * @throws IllegalStateException if this queue is full
10      * @throws NullPointerException if the specified element is null
11      */
12     public boolean add(E e) {    //add 和offer(e) 是一样的
13         return super.add(e);
14     }
15 
16     /**
17      * Inserts the specified element at the tail of this queue if it is
18      * possible to do so immediately without exceeding the queue's capacity,
19      * returning {@code true} upon success and {@code false} if this queue
20      * is full.  This method is generally preferable to method {@link #add},
21      * which can fail to insert an element only by throwing an exception.
22      *
23      * @throws NullPointerException if the specified element is null
24      */
25     public boolean offer(E e) {
26         checkNotNull(e);
27         final ReentrantLock lock = this.lock;
28         lock.lock();
29         try {
30             if (count == items.length)
31                 return false;
32             else {
33                 insert(e);
34                 return true;
35             }
36         } finally {
37             lock.unlock();
38         }
39     }
40 
41     /**
42      * Inserts the specified element at the tail of this queue, waiting
43      * for space to become available if the queue is full.
44      *
45      * @throws InterruptedException {@inheritDoc}
46      * @throws NullPointerException {@inheritDoc}
47      */
48     public void put(E e) throws InterruptedException {
49         checkNotNull(e);
50         final ReentrantLock lock = this.lock;
51         lock.lockInterruptibly();
52         try {
53             while (count == items.length)
54                 notFull.await();
55             insert(e);
56         } finally {
57             lock.unlock();
58         }
59     }
60 
61     /**
62      * Inserts the specified element at the tail of this queue, waiting
63      * up to the specified wait time for space to become available if
64      * the queue is full.
65      *
66      * @throws InterruptedException {@inheritDoc}
67      * @throws NullPointerException {@inheritDoc}
68      */
69     public boolean offer(E e, long timeout, TimeUnit unit)   // 限时等待添加
70         throws InterruptedException {
71 
72         checkNotNull(e);
73         long nanos = unit.toNanos(timeout);
74         final ReentrantLock lock = this.lock;
75         lock.lockInterruptibly();
76         try {
77             while (count == items.length) {
78                 if (nanos <= 0)
79                     return false;
80                 nanos = notFull.awaitNanos(nanos);
81             }
82             insert(e);
83             return true;
84         } finally {
85             lock.unlock();
86         }
87     }

对元素的获取同样提供了三种使用场景:添加(队列空则返回null)、限时等待获取,无限等待获取;

 1  public E poll() {
 2         final ReentrantLock lock = this.lock;
 3         lock.lock();
 4         try {
 5             return (count == 0) ? null : extract();
 6         } finally {
 7             lock.unlock();
 8         }
 9     }
10 
11     public E take() throws InterruptedException {
12         final ReentrantLock lock = this.lock;
13         lock.lockInterruptibly();
14         try {
15             while (count == 0)
16                 notEmpty.await();
17             return extract();
18         } finally {
19             lock.unlock();
20         }
21     }
22 
23     public E poll(long timeout, TimeUnit unit) throws InterruptedException {
24         long nanos = unit.toNanos(timeout);
25         final ReentrantLock lock = this.lock;
26         lock.lockInterruptibly();
27         try {
28             while (count == 0) {
29                 if (nanos <= 0)
30                     return null;
31                 nanos = notEmpty.awaitNanos(nanos);
32             }
33             return extract();
34         } finally {
35             lock.unlock();
36         }
37     }

获取队列元素大小也是强一致性的:

 1   /**
 2      * Returns the number of elements in this queue.
 3      *
 4      * @return the number of elements in this queue
 5      */
 6     public int size() {
 7         final ReentrantLock lock = this.lock;
 8         lock.lock();
 9         try {
10             return count;
11         } finally {
12             lock.unlock();
13         }
14     }

元素的删除也是同步的,元素存在则删除返回true,如果元素不存在则返回false:

 1   /**
 2      * Removes a single instance of the specified element from this queue,
 3      * if it is present.  More formally, removes an element {@code e} such
 4      * that {@code o.equals(e)}, if this queue contains one or more such
 5      * elements.
 6      * Returns {@code true} if this queue contained the specified element
 7      * (or equivalently, if this queue changed as a result of the call).
 8      *
 9      * <p>Removal of interior elements in circular array based queues
10      * is an intrinsically slow and disruptive operation, so should
11      * be undertaken only in exceptional circumstances, ideally
12      * only when the queue is known not to be accessible by other
13      * threads.
14      *
15      * @param o element to be removed from this queue, if present
16      * @return {@code true} if this queue changed as a result of the call
17      */
18     public boolean remove(Object o) {
19         if (o == null) return false;
20         final Object[] items = this.items;
21         final ReentrantLock lock = this.lock;
22         lock.lock();
23         try {
24             for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) {
25                 if (o.equals(items[i])) {
26                     removeAt(i);
27                     return true;
28                 }
29             }
30             return false;
31         } finally {
32             lock.unlock();
33         }
34     }

ArrayBlockingQueue的所有操作都是通过加锁进行同步的,代码也比较简单。



posted on 2016-04-29 16:55  jessezeng  阅读(320)  评论(0编辑  收藏  举报

导航