LinkEdBlockingQueue源码分析
底层基于链表实现,可指定长度,不指定默认
局部变量
private final int capacity;//队列长度
private final AtomicInteger count = new AtomicInteger();//由于底层是链表,需要一个原子性变量记录元素数量
transient Node<E> head; //链表头节点,取数据的节点
private transient Node<E> last; //链表尾节点,存数据节点
/**
* 由于是链表的数据结构,写数据和读数据不适用同一个锁和Condition对象
*/
private final ReentrantLock takeLock = new ReentrantLock();
private final Condition notEmpty = takeLock.newCondition();
private final ReentrantLock putLock = new ReentrantLock();
private final Condition notFull = putLock.newCondition();
静态内部类Node
static class Node<E> {
//存储队列元素
E item;
//单项链表,存储下一个Node节点
Node<E> next;
//构造方法
Node(E x) { item = x; }
}
构造方法
//无惨构造,默认长度为Integer最大长度
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);
//写锁,要避免并发问题,防止在对象创建完后和添加集合c中元素之前有其它线程添加元素
final ReentrantLock putLock = this.putLock;
putLock.lock();
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();
}
}
添加元素相关方法
enqueue(Node node)添加元素的逻辑
private void enqueue(Node<E> node) {
//将尾节点的下一个节点设置为当前节点,然后将当前节点作为最后一个节点
last = last.next = node;
}
put(E e)方法
public void put(E e) throws InterruptedException {
//非空校验
if (e == null) throw new NullPointerException();
final int c;
//封装node节点
final Node<E> node = new Node<E>(e);
//写锁
final ReentrantLock putLock = this.putLock;
//拿到队列长度
final AtomicInteger count = this.count;
//允许被打断
putLock.lockInterruptibly();
try {
//队列已满,挂起线程
while (count.get() == capacity) {
notFull.await();
}
//添加元素
enqueue(node);
//拿到师叔祖元素个数然后+1操作
c = count.getAndIncrement();
//如果添加完元素,队列没有慢,通知其它要添加数据的挂起线程
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
//如果添加元素前,队列为空,通知消费者
signalNotEmpty();
}
//通知阻塞的消费者线程
private void signalNotEmpty() {
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
notEmpty.signal();
} finally {
takeLock.unlock();
}
}
offer(E e)方法
public boolean offer(E e) {
//非空校验
if (e == null) throw new NullPointerException();
//获取队列长度
final AtomicInteger count = this.count;
//如果队列满了,添加失败,返回false
if (count.get() == capacity)
return false;
final int c;
//封装node
final Node<E> node = new Node<E>(e);
//写锁
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
//DCL再次判断队列是否满了
if (count.get() == capacity)
return false;
enqueue(node);
c = count.getAndIncrement();
//添加元素后队列没满,通知其它生产者线程
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
//添加前队列为空,通知其它消费者线程
if (c == 0)
signalNotEmpty();
return true;
}
offer(E e, long timeout, TimeUnit unit)
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
if (e == null) throw new NullPointerException();
long nanos = unit.toNanos(timeout);
final int c;
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
//队列已慢,挂起指定时间线程
while (count.get() == capacity) {
if (nanos <= 0L)
return false;
nanos = notFull.awaitNanos(nanos);
}
enqueue(new Node<E>(e));
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
return true;
}
获取元素相关方法
dequeue()链表中移除node节点,并返回节点内元素
private E dequeue() {
// assert takeLock.isHeldByCurrentThread();
// assert head.item == null;
Node<E> h = head;
Node<E> first = h.next;
h.next = h; // help GC
head = first;
E x = first.item;
first.item = null;
return x;
}
poll()方法
public E poll() {
//获取元素数量
final AtomicInteger count = this.count;
//如果队列为空,返回null
if (count.get() == 0)
return null;
final E x;
final int c;
//读锁
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
//DCL判断元素为空,返回null
if (count.get() == 0)
return null;
//移除元素
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
poll(long timeout, TimeUnit unit)方法,指定时间内阻塞
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
final E x;
final int c;
long nanos = unit.toNanos(timeout);
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
if (nanos <= 0L)
return null;
nanos = notEmpty.awaitNanos(nanos);
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
peek()方法,不移除元素,只返回节点内元素
public E peek() {
final AtomicInteger count = this.count;
if (count.get() == 0)
return null;
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try
//返回头节点的下一个元素
return (count.get() > 0) ? head.next.item : null;
} finally {
takeLock.unlock();
}
}
add()/remove()
这两个方法是在AbstractQueue类中定义,调用实现类中的poll()方法,做异常处理。