抽象队列与阻塞队列解析

抽象队列

AbstractQueue 是个抽象类,继承 AbstractCollection,实现 Queue 接口。其中 AbstractCollection 也是个抽象类,实现了 Collection 接口。所以 AbstractQueue 实现了集合的方法,和常用的 ArrayList 等类似。

1
2
3
4
5
public abstract class AbstractQueue<E> extends AbstractCollection<E> implements Queue<E> {
// 被子类使用的构造器
protected AbstractQueue() {
}
}

AbstractQueue 还实现 Queue 接口,Queue 源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface Queue<E> extends Collection<E> {
// 将元素 e 插入队列尾部,插入成功返回 true。如果在超出 JVM 限制的时候用 add 方法会抛出异常
boolean add(E e);

// 将元素 e 插入队列尾部,插入成功返回 true。如果在超出 JVM 限制的时候用 offer 方法会返回false
boolean offer(E e);

// 检索并移除此队列的头,队列为空则抛出 NoSuchElementException
E remove();

// 检索并移除此队列的头,队列为空则返回 null
E poll();

// 检索但不移除此队列的头,队列为空则抛出 NoSuchElementException
E element();

// 检索但不移除此队列的头,队列为空则返回 null
E peek();
}

AbstractQueue 在实现 add(E e) 方法时,调用 offer(E e) 添加失败则抛出异常 IllegalStateException("Queue full")。实现 remove() 方法时,调用 poll() 方法返回 null 则抛出异常 NoSuchElementException()。实现 element() 方法时,调用 peek() 方法返回 null 则抛出异常 NoSuchElementException()

除了以上方法外,AbstractQueue 还实现了 clear()addAll(Collection<? extends E> c) 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 清空队列元素
public void clear() {
while (poll() != null)
;
}

// 将集合中的元素全部加到队列,全部添加成功则返回 true。
// 如果集合为 null,则抛出空指针异常。如果集合和当前队列是一个,则抛出 IllegalArgumentException 异常
public boolean addAll(Collection<? extends E> c) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}

阻塞队列

在 JUC 中,BlockingQueue 很好的解决了多线程中如何高效安全“传输”数据的问题,通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。

接口中定义的方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public interface BlockingQueue<E> extends Queue<E> {
// 将元素 e 插入队列尾部,参见 `Queue` 接口的 add 方法
boolean add(E e);

// 将元素 e 插入队列尾部,参见 `Queue` 接口的 offer 方法
boolean offer(E e);

// 将指定的元素插队列尾部,当空间不可用时会等待。
void put(E e) throws InterruptedException;

// 将指定的元素插队列尾部,当空间不可用时会等待,直到超时。
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;

// 遍历并移除队列头部元素,如果队列为空则阻塞直至有元素可移除。
E take() throws InterruptedException;

// take() 的超时版本
E poll(long timeout, TimeUnit unit) throws InterruptedException;

// 返回此队列在理想情况下(在没有内存或资源约束的情况下)可以不阻塞地接受的元素的数目
// 如果没有内在限制,则返回{@code integer.max_value}
int remainingCapacity();

// 检索并移除此队列的头,参见 `Queue` 接口的 remove 方法。
boolean remove(Object o);

// 是否包含,参见 Collection 接口的 contains 方法。
public boolean contains(Object o);

// 从队列中移除所有可用元素并将它们添加到给定集合中。
int drainTo(Collection<? super E> c);

// 从队列中移除指定数量的可用元素并将它们添加到给定集合中。
int drainTo(Collection<? super E> c, int maxElements);
}