)
25 public E next() {
26 if (! hasNext())
27 throw new NoSuchElementException();
28 return (E) snapshot[cursor++];
29 }
30
31 // 获取上一个元素。
32 @SuppressWarnings("unchecked")
33 public E previous() {
34 if (! hasPrevious())
35 throw new NoSuchElementException();
36 return (E) snapshot[--cursor];
37 }
38
39 // 获取下一个元素的位置。
40 public int nextIndex() {
41 return cursor;
42 }
43
44 // 获取上一个元素的位置。
45 public int previousIndex() {
46 return cursor-1;
47 }
48
49 // 不支持删除元素。
50 public void remove() {
51 throw new UnsupportedOperationException();
52 }
53
54 // 不支持修改元素。
55 public void set(E e) {
56 throw new UnsupportedOperationException();
57 }
58
59 // 不支持添加元素。
60 public void add(E e) {
61 throw new UnsupportedOperationException();
62 }
63
64 // Java1.8新增的方法,使用迭代器Iterator的所有元素,并且第二次调用它将不会做任何事情。
65 @Override
66 public void forEachRemaining(Consumer<? super E> action) {
67 Objects.requireNonNull(action);
68 Object[] elements = snapshot;
69 final int size = elements.length;
70 for (int i = cursor; i < size; i++) {
71 @SuppressWarnings("unchecked") E e = (E) elements[i];
72 action.accept(e);
73 }
74 cursor = size;
75 }
76 }
ArrayBlockingQueue
说明
ArrayBlockingQueue内部是通过Object[]数组保存数据的,也就是说ArrayBlockingQueue本质上是通过数组实现的。ArrayBlockingQueue的大小,即数组的容量是创建ArrayBlockingQueue时指定的。
ArrayBlockingQueue与ReentrantLock是组合关系,ArrayBlockingQueue中包含一个ReentrantLock对象。ReentrantLock是可重入的互斥锁,ArrayBlockingQueue就是根据该互斥锁实现“多线程对竞争资源的互斥访问”。而且,ReentrantLock分为公平锁和非公平锁,关于具体使用公平锁还是非公平锁,在创建ArrayBlockingQueue时可以指定,ArrayBlockingQueue默认会使用非公平锁。
ArrayBlockingQueue与Condition是组合关系,ArrayBlockingQueue中包含两个Condition对象。而且,Condition又依赖于ArrayBlockingQueue而存在,通过Condition可以实现对ArrayBlockingQueue的更精确的访问。
构造方法
1 public ArrayBlockingQueue(int capacity) {
2 this(capacity, false);
3 }
4
5 public ArrayBlockingQueue(int capacity, boolean fair) {
6 if (capacity <= 0)
7 throw new IllegalArgumentException();
8 this.items = new Object[capacity];
9 lock = new ReentrantLock(fair);
10 notEmpty = lock.newCondition();
11 notFull = lock.newCondition();
12 }
13
14 public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) {
15 this(capacity, fair);
16 // 加锁是为了保证可见性,因为可能存在其他线程在初始化之后修改集合。
17 final ReentrantLock lock = this.lock;
18 lock.lock();
19 try {
20 int i = 0;
21 try {
22 for (E e : c) {
23 checkNotNull(e);
24 items[i++] = e;
25 }
26 } catch (ArrayIndexOutOfBoundsException ex) {
27 throw new IllegalArgumentException();
28 }
29 count = i;
30 putIndex = (i == capacity) ? 0 : i;
31 } finally {
32 lock.unlock();
33 }
34 }
添加元素
ArrayBlockingQueue提供了offer()方法和put()方法两种方式添加元素。
offer()方法添加失败会立即返回false,并且添加过程中不允许被其他线程中断。
put()方法添加失败会等待,并且在添加过程中可以被其他线程中断,抛出InterruptedException异常。
1 // 不允许被其他线程中断,添加失败则立即返回false。
2 public boolean offer(E e) {
3 checkNotNull(e);
4 final ReentrantLock lock = this.lock;
5 lock.lock();
6 try {
7 if (count == items.length)
8 return false;
9 else {
10 enqueue(e);
11 return true;
12 }
13 } finally {
14 lock.unlock();
15 }
16 }
17
18 // 允许被其他线程中断,抛出InterruptedException,并且添加失败会等待。
19 public void put(E e) throws InterruptedException {
20 checkNotNull(e);
21 final ReentrantLock lock = this.lock;
22 lock.lockInterru