1. 整体类图
从图上可以看到,内容主要可以分成2个部分,分别为Queue队列、Deque双端队列,其中Deque还提供了Stack栈的功能。
2. Queue相关
2.1 Queue接口
提供了队列的通用操作方法声明。可以看做一个排队队伍,新来的人要排在队尾(新增/offer),按次序叫号,最先叫的都是队首(获取/poll)。
/**
* 队列接口
* 提供了两套操作队列方法:
* 1)抛异常, add/remove/element
* 2) 返回false/null,offer/poll/peek
* 并不强求实现类满足(FIFO先进先出)顺序要求。比如Stack(LIFO后进先出)、优先队列
* @since 1.5
*/
public interface Queue<E> extends Collection<E> {
/**
* 队尾插入元素
* 如果空间达到上限,抛异常IllegalStateException
*/
boolean add(E e);
/**
* 从队首获取并删除元素
* 如果队列为空,抛NoSuchElementException 异常,
*/
E remove();
/**
* 获取队首元素,并不移除
* 如果队列为空,抛NoSuchElementException异常
*/
E element();
/**
* 队尾插入元素
*/
boolean offer(E e);
/**
* 从对手获取并删除元素
* 如果队列为空,返回null
*/
E poll();
/**
* 获取对手元素,并不删除
* 如果队列为空,返回null
*/
E peek();
}
2.2 AbstractQueue抽象类
基于Queue接口方法做了一定的内部封装
/**
* 提供了部分队列操作的实现。
* 添加(offer)、删除(poll)、获取元素(peek)操作
* 失败抛异常,而不是返回false/null
* 不允许null值
* @since 1.5
*/
public abstract class AbstractQueue<E>
extends AbstractCollection<E>
implements Queue<E> {
/**
* 子类调用的默认构造
*/
protected AbstractQueue()
/**
* 往队列中添加元素
* 添加成功,返回true
* 如果容量达到上限,抛异常 IllegalStateException
*/
public boolean add(E e)
/**
* 移除队列头元素并返回
* NoSuchElementException 无元素异常
*/
public E remove()
/**
* 提取队列头元素,不删除。
* 区别于peek方法,当队列空时,抛NoSuchElementException无元素异常
*/
public E element()
/**
* 清空队列中所有元素
* 通过poll方法实现
*/
public void clear() {
while (poll() != null)
;
}
/**
* 从集合c中添加所有元素进队列。
* 如果添加的是队列本身,抛异常IllegalStateException
* 添加的元素顺序遵从集合迭代器迭代顺序
*/
public boolean addAll(Collection<? extends E> c)
}
2.3 BlockingQueue阻塞队列接口
其内部方法主要分为四种返回
1)抛异常
2) 返回值
3) 操作无期限阻塞,直到满足条件
4) 操作在给定时间内有限阻塞
方法主要分为如下三种类型:
非阻塞方法:add、offer、remove、poll
无限期阻塞:put、take
有限时间阻塞:offer(时间)、poll(时间)
/**
* 阻塞队列接口
* 获取元素时如果队列为空。操作阻塞直到有元素插入队列
* 插入元素时如果空间上限。插入阻塞直到空间腾出来
* 不允许null值,会抛NullPointerException
*
* 线程安全
* @since 1.5
*/
public interface BlockingQueue<E> extends Queue<E> {
/**
* 往队尾添加元素 (非阻塞)
* 如果容量上限,抛异常IllegalStateException
*/
boolean add(E e);
/**
* 往队尾添加元素 (非阻塞)
* 如果容量上限,抛异常IllegalStateException
*/
boolean offer(E e);
/**
* 往队尾添加元素 (无期限阻塞)
* 如果容量上限,阻塞直到有空余容量
* 如果线程中断,抛异常InterruptedException
*/
void put(E e) throws InterruptedException;
/**
* 往队尾添加元素 (有限时间阻塞)
* 如果达到最大时间,线程中断,抛异常InterruptedException
*/
boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException;
/**
* 从队首获取并删除元素 (无期限阻塞)
* 如果队列为空,阻塞直到有元素
* 如果线程中断,抛异常InterruptedException
*/
E take() throws InterruptedException;
/**
* 从队首获取并删除元素 (有限时间阻塞)
* 如果达到最大时间,线程中断,抛异常InterruptedException
*/
E poll(long timeout, TimeUnit unit)
throws InterruptedException;
/**
* 队列剩余容量
*/
int remainingCapacity();
/**
* 从队列元素中移除单个特定元素(非阻塞)
* 如果不存在,抛异常NullPointerException
*/
boolean remove(Object o);
/**
* 判断队列中是否存在特定元素
* 如果没有,抛异常NullPointerException
*/
public boolean contains(Object o);
/**
* 移除队列中所有元素,并将元素放到给定集合c中
*/
int drainTo(Collection<? super E> c);
/**
* 移除队列中所有元素,并将元素放到给定集合c中.最多只迁移maxElements个元素
*/
int drainTo(Collection<? super E> c, int maxElements);
}
2.4 ArrayBlockingQueue基于数组的阻塞队列
2.4.1 数据结构
固定容量的循环数组
2.4.2 线程安全
ArrayBlockingQueue类内有三个主要用于线程同步的变量
// 可重入锁,并发环境下主要的加锁方案
final ReentrantLock lock;
// 阻塞取的标志条件
private final Condition notEmpty;
// 阻塞插的标志条件
private final Condition notFull;
2.4.3 源码
/**
* 基于数组实现的有界阻塞队列
* 元素顺序FIFO先进先出。队尾插数据,队首取数据
* 初始化后 容量不可变
* @since 1.5
*/
public class ArrayBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
// 队列元素底层数组存储(循环数组)
final Object[] items;
// 队首索引
int takeIndex;
// 队尾索引
int putIndex;
// 队列元素量
int count;
// 可重入锁,并发环境下主要的加锁方案
final ReentrantLock lock;
// 阻塞取的标志条件
private final Condition notEmpty;
// 阻塞插的标志条件
private final Condition notFull;
transient Itrs itrs = null;
/**
* 辅助方法 - 循环获取索引
*/
final int dec(int i)
/**
* 辅助方法 - 返回索引i上的元素
*/
final E itemAt(int i)
/**
* 辅助方法 - 判断元素是否为空
*/
private static void checkNotNull(Object v)
/**
* 插入元素
*/
private void enqueue(E x) {
final Object[] items = this.items;
items[putIndex] = x;
// 如果已经到数组尾,循环设置尾部到索引位置0
if (++putIndex == items.length)
putIndex = 0;
count++;
// 阻塞取的释放信号
notEmpty.signal();
}
/**
* 提取并删除元素
*/
private E dequeue() {
final Object[] items = this.items;
E x = (E) items[takeIndex];
items[takeIndex] = null;
// 如果已经到数组尾,循环设置尾部到索引位置0
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
// 阻塞插的释放信号
notFull.signal();
return x;
}
/**
* 删除指定索引位的元素
*/
void removeAt(final int removeIndex) {
final Object[] items = this.items;
// 移除元素刚好在队列头
if (removeIndex == takeIndex) {
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
// 迭代器起始移到下一个
if (itrs != null)
itrs.elementDequeued();
} else {
final int putIndex = this.putIndex;
// 循环将索引后的所有数组元素前移一位
for (int i = removeIndex;;) {
int next = i + 1;
if (next == items.length)
next = 0;
if (next != putIndex) {
items[i] = items[next];
i = next;
} else {
items[i] = null;
this.putIndex = i;
break;
}
}
count--;
// 迭代器内部更新
if (itrs != null)
itrs.removedAt(removeIndex);
}
// 阻塞插的释放信号
notFull.signal();
}
/**
* 构造指定容量,默认策略(公平锁、非抢占式)的ArrayBlockingQueue
*/
public ArrayBlockingQueue(int capacity) {
this(capacity, false);
}
/**
* 构造指定容量,指定策略的ArrayBlockingQueue
*/
public ArrayBlockingQueue(int capacity, boolean fair)
/**
* 从给定集合c中,构造指定容量,指定策略的ArrayBlockingQueue
*/
public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c)
/**
* 队尾添加元素
* 如果容量上限,抛异常IllegalStateException
*/
public boolean add(E e)
/**
* 队尾插入元素
* 如果容量上限,返回false
*/
public boolean offer(E e)
/**
* 队尾插入元素(无限阻塞)
*/
public void put(E e) throws InterruptedException
/**
* 队尾插入元素(有限时间阻塞)
*/
public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException
public E poll()
public E take() throws InterruptedException
public E poll(long timeout, TimeUnit unit) throws InterruptedException
public E peek()
/**
* 返回队列的元素数量
*/
public int size()
/**
* 返回队列中剩余的容量
*/
public int remainingCapacity()
/**
* 移除队列中首次出现的元素
*/
public boolean remove(Object o)
/**
* 判断队列中是否包含指定元素
*/
public boolean contains(Object o)
/**
* 将队列元素转成数组
*/
public Object[] toArray()
/**
* 将队列元素转成数组,
* 如果容量大于给定数组元素,新建数组
*/
public <T> T[] toArray(T[] a)
public String toString()
public void clear()
/**
* 将队列中元素迁移至集合c
*/
public int drainTo(Collection<? super E> c)
/**
* 将队列中元素迁移至集合c,最多添加maxElements个元素
*/
public int drainTo(Collection<? super E> c, int maxElements)
/**
* 返回迭代器
*/
public Iterator<E> iterator()
/**
* 返回可分割的迭代器
* @since 1.8
*/
public Spliterator<E> spliterator()
}
2.5 LinkedBlockingQueue基于链表的阻塞队列
2.5.1 数据结构
基于单向链表实现
2.5.2 线程安全
采用可重入锁方式实现。
// 可重入锁:获取元素锁
private final ReentrantLock takeLock = new ReentrantLock();
// 队列非空标志。插入元素后触发其释放信号
private final Condition notEmpty = takeLock.newCondition();
// 可重入锁:插入元素锁
private final ReentrantLock putLock = new ReentrantLock();
// 队列未满标志。获取数据后触发其释放信号
private final Condition notFull = putLock.newCondition();
2.5.3 源码
/**
* 基于链表的阻塞队列。
* 队列顺序满足FIFO先进先出模式
* @since 1.5
*/
public class LinkedBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
/**
* 链表节点类
*/
static class Node<E> {
E item;
Node<E> next;
Node(E x) {
item = x; }
}
// 容量上限,不指定的话默认就是Integer.MAX_VALUE
private final int capacity;
// 原子类记录元素数量
private final AtomicInteger count = new AtomicInteger();
// 队列虚头(真实的元素为其head.next)
transient Node<E> head;
// 链表尾部
private transient Node<E> last