JUC 之 队列基础篇讲解
本篇将详细讲解队列的接口实现,为后续篇章的讲解做铺垫。Java 是面向对象的语言,面向对象的原则则是高度抽象,所以我们先来看接口,看看它提供了哪些功能。
Queue 接口
Queue 接口继承自 Collection 接口,说明队列也是一个集合容器,用来存储数据的。通常队列的实现方式为FIFO(先进先出)或 LIFO(后进先出),总是从一头插入一头取数据。下面我们来看看 Queue 额外提供了什么功能。
public interface Queue<E> extends Collection<E> {
// 向队列中添加元素,成功返回 true,如果队列有容量限制并且队列已满,则抛出IllegalStateException异常。在使用容量受限的队列时,通常建议使用offer。
boolean add(E e);
// 向队列中添加元素,成功返回 true,如果队列有容量限制并且队列已满,返回 false
boolean offer(E e);
// 从队列头部移除元素,队列为空时抛出异常
E remove();
// 从队列头部移除元素,队列为空时返回 null
E poll();
// 获取队列头部元素但是不删除,队列为空时抛出异常
E element();
// 获取队列头部元素但是不删除,队列为空时返回 null
E peek();
}
通过上述源码我们看到 Queue 接口只提供了队列基础的添加删除功能。
BlockingQueue 接口
BlockingQueue 接口继承自 Queue 接口,提供队列的阻塞操作功能
public interface BlockingQueue<E> extends Queue<E> {
// 向队列中添加元素,当队列满时将阻塞等待队列有可用容量
void put(E e) throws InterruptedException;
// 向队列中添加元素,成功返回 true,如果队列有容量限制并且队列已满,等待指定时间,如果队列还是没有容量将返回 false
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
// 从队列头部获取(移除)元素,队列为空阻塞等待知道有元素添加到队列中,阻塞过程中可被中断唤醒
E take() throws InterruptedException;
// 从队列头部获取(移除)元素,队列为空时,阻塞等待指定时间,还是没有可用元素返回 null,阻塞过程中可被中断唤醒
E poll(long timeout, TimeUnit unit) throws InterruptedException;
// 获取队列剩余可用容量
int remainingCapacity();
// 从队列中移除指定元素
boolean remove(Object o);
// 判断队列中是否存在指定元素
public boolean contains(Object o);
// 移除队列中所有元素将其添加到指定集合中
int drainTo(Collection<? super E> c);
// 从队列中移除指定数量的元素将其添加到给定集合中
int drainTo(Collection<? super E> c, int maxElements);
}
Deque 接口
Deque 继承自 Queue 接口,支持两端插入或取数据,也即支持双端队列实现。
public interface Deque<E> extends Queue<E> {
// 向队列头部添加元素
void addFirst(E e);
boolean offerFirst(E e);
// 从队列头部获取元素,队列为空时返回 null
E pollFirst();
// 获取队列头部元素,但不从队列中删除,队列为空时抛出异常
E getFirst();
// 获取队列头部元素,但不从队列中删除,队列为空时返回 null
E peekFirst();
// 向队列尾部添加元素
void addLast(E e);
boolean offerLast(E e);
// 从队列头部移除元素
E removeFirst();
// 从队列尾部移除元素
E removeLast();
// 从队列尾部获取元素,队列为空时返回 null
E pollLast();
// 获取队列尾部元素,但不从队列中删除,队列为空时抛出异常
E getLast();
// 获取队列尾部元素,但不从队列中删除,队列为空时返回 null
E peekLast();
// *** Stack methods ***
// 双端队列实现栈
void push(E e);
E pop();
}
BlockingDeque 接口
BlockingDeque 继承自 Deque 接口,提供阻塞行为支撑
public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
// 向队列头添加元素,队列满时阻塞等待,阻塞过程中可被中断唤醒
void putFirst(E e) throws InterruptedException;
// 向队列尾添加元素,队列满时阻塞等待,阻塞过程中可被中断唤醒
void putLast(E e) throws InterruptedException;
// 向队列头添加元素,队列满时阻塞等待指定时间,唤醒后队列中还是没有空间返回 false
boolean offerFirst(E e, long timeout, TimeUnit unit) throws InterruptedException;
// 向队列尾添加元素,队列满时阻塞等待指定时间,唤醒后队列中还是没有空间返回 false
boolean offerLast(E e, long timeout, TimeUnit unit) throws InterruptedException;
// 从队列头获取元素,队列空时阻塞等待直到队列中有数据,可被中断唤醒
E takeFirst() throws InterruptedException;
// 从队列尾获取元素,队列空时阻塞等待直到队列中有数据,可被中断唤醒
E takeLast() throws InterruptedException;
// 从队列头取数据,队列空时阻塞等待指定时间,唤醒后队列中还是没有数据返回 null,可被中断唤醒
E pollFirst(long timeout, TimeUnit unit) throws InterruptedException;
// 从队列尾取数据,队列空时阻塞等待指定时间,唤醒后队列中还是没有数据返回 null,可被中断唤醒
E pollLast(long timeout, TimeUnit unit) throws InterruptedException;
// 向队列中添加元素,队列满时阻塞等待,可被中断唤醒
void put(E e) throws InterruptedException;
// 从队列头取数据,队列空时阻塞等待,可被中断唤醒
E take() throws InterruptedException;
}
AbstractQueue 抽象类
采用模板方法设计模式,抽象类提供公共算法实现。
public abstract class AbstractQueue<E> extends AbstractCollection<E> implements Queue<E> {
// 添加元素实现,调用 offer 方法完成具体添加操作
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
// 从队列头部移除元素
public E remove() {
E x = poll();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
// 获取元素实现,具体由 peek 方法实现
public E element() {
E x = peek();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
// 清空队列
public void clear() {
while (poll() != null)
;
}
// 将集合中的所有元素添加到队列中,具体添加动作由 add 方法实现
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;
}
}
总结:了解了其接口设计和抽象类的实现,下面的篇幅我们将学习具体队列的源码实现,本篇先介绍到这里。