1. LinkedBlockingQueue
概述
LinkedBlockingQueue
来自于 jdk 1.5
的 JUC
包,是一个 线程安全的无界(严格意义上是有界)阻塞队列,底层数据结构是一个单链表
- 它的容量范围是
{1, Integer.MAX_VALUE}
,可以指定容量,如未指定容量,则默认容量等于 Integer.MAX_VALUE
,所以 LinkedBlockingQueue
亦成为无界阻塞队列
- 由于出队线程只操作队头,而入队线程只操作队尾,这里巧妙地采用了两把锁,对插入数据采用
putLock
,对移除数据采用 takeLock
,即入队锁和出队锁,这样避免了出队线程和入队线程竞争同一把锁的现象
- 添加和删除操作并 不是互斥操作,可以同时进行,这样也就可以大大提高吞吐量
LinkedBlockingQueue
的工作模式都是 非公平 的,也不能手动指定为公平模式,这样的好处是可以提升并发量
2. LinkedBlockingQueue
源码
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526124130302.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zODE5MjQyNw==,size_16,color_FFFFFF,t_70#pic_center)
2.1. LinkedBlockingQueue
数据结构(单链表)
static class Node<E> {
E item;
Node<E> next;
Node(E x) {
item = x; }
}
2.2. LinkedBlockingQueue
主要属性
private final int capacity;
private final AtomicInteger count = new AtomicInteger();
transient Node<E> head;
private transient Node<E> last;
private final ReentrantLock takeLock = new ReentrantLock();
private final Condition notEmpty = takeLock.newCondition();
private final ReentrantLock putLock = new ReentrantLock();
private final Condition notFull = putLock.newCondition();
- 采用单链表结构来保存数据,因此具有头、尾结点的引用
head、last
,链表结点类型是内部类 Node
类型
LinkedBlockingQueue
的容量最大是 Integer.MAX_VALUE
。使用一个 AtomicInteger
类型的原子变量 count
来作为计数器,它是线程安全的
takeLock
作为消费线程获取的锁,同时有个对应的 notEmpty
条件对象用于消费线程的阻塞和唤醒
putLock
作为生产线程获取的锁,同时有个对应的 notFull
条件对象用于生产线程的阻塞和唤醒
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210527224608229.png#pic_center)
2.3. LinkedBlockingQueue
构造函数
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
public LinkedBlockingQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
last = head = new Node<E>(null);
}
public LinkedBlockingQueue(Collection<? extends E> c) {
this(Integer.MAX_VALUE);
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
int n = 0;
for (E e : c)