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的所有操作都是通过加锁进行同步的,代码也比较简单。