LinkedBlockingQueue 特点
LinkedBlockingQueue 通常叫做链表阻塞队列,从命名可以知道,其底层数据是链表,且队列是可阻塞的。LinkedBlockingQueue 的特点:
基于链表实现的阻塞队列,底层的数据结构为链表
基于链表实现先入先出的队列,新元素放在队尾,从队头部获取元素
链表大小在初始化的时候可以设置大小,默认为 Integer 的最大值
可以使用 Iterator 进行迭代
属性
源码:
public class LinkedBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
private static final long serialVersionUID = -6903933977591709194L;
/**
* Linked list node class
*/
static class Node<E> {
E item;
/**
* One of:
* - the real successor Node
* - this Node, meaning the successor is head.next
* - null, meaning there is no successor (this is the last node)
*/
Node<E> next;
Node(E x) { item = x; }
}
/** The capacity bound, or Integer.MAX_VALUE if none */
private final int capacity;
/** Current number of elements */
private final AtomicInteger count = new AtomicInteger();
/**
* Head of linked list.
* Invariant: head.item == null
*/
transient Node<E> head;
/**
* Tail of linked list.
* Invariant: last.next == null
*/
private transient Node<E> last;
/** Lock held by take, poll, etc */
private final ReentrantLock takeLock = new ReentrantLock();
/** Wait queue for waiting takes */
private final Condition notEmpty = takeLock.newCondition();
/** Lock held by put, offer, etc */
private final ReentrantLock putLock = new ReentrantLock();
/** Wait queue for waiting puts */
private final Condition notFull = putLock.newCondition();
......
}
复制代码
static class Node<E>
表示链表的元素节点
Node<E> next;
表示当前元素指向的下一个节点,如果为 null,则表示当前节点为最后一个节点
private final int capacity;
链表的容量,默认 Integer.MAX_VALUE
private final AtomicInteger count = new AtomicInteger();
链表已有元素大小,使用 AtomicInteger,所以是线程安全的
transient Node<E> head;
链表头
private transient Node<E> last;
链表尾
private final ReentrantLock takeLock = new ReentrantLock();
take 时的锁
private final Condition notEmpty = takeLock.newCondition();
take 的条件队列
private final ReentrantLock putLock = new ReentrantLock();
put 时的锁
private final Condition notFull = putLock.newCondition();
put 的条件队列
总结:设计了两把锁,一个是 take 锁,一个是 put 锁,目的是为了让两个操作互相不干扰,同步进行
初始化
源码:
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(); // Never contended, but necessary for visibility
try {
int n = 0;
for (E e : c) {
if (e == null)
throw new NullPointerException();
if (n == capacity)
throw new IllegalStateException("Queue full");
enqueue(new Node<E>(e));
++n;
}
count.set(n);
} finally {
putLock.unlock();
}
}
复制代码
源码中提供了三种初始化的方式:第一种:使用默认的 Integer 的最大值进行初始化第二种:指定链表容量大小初始化第三章:使用已有集合数据进行初始化
评论