/**
* LinkedBlockingQueue中节点类
*/
static class Node<E> {
E item;
Node<E> next;
Node(E x) { item = x; }
}
/** LinkedBlockingQueue 容量 默认为 Integer.MAX_VALUE
* 如果使用默认值后需考虑消费线程消费速度小于生产线程生产速度的情况
* 不然内存爆满导致频繁 full gc
*/
private final int capacity;
/** 队列中元素个数,因为生产者消费者 持有不同锁所以对count的更新通过原子方式更新 */
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();
LinkedBlockingQueue构造函数分析
/**
* 默认构造方法使用Integer.MAX_VALUE作为队列容量可以理解为无界
*
*/
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
/**
* 指定队列容量 capacity 初始化头尾指针
*/
public LinkedBlockingQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
last = head = new Node<E>(null);
}
/**
* 通过已有集合初始化LinkedBlockingQueue
* 获取生产者锁后将元素入队
*/
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();
}
}
/**
* 生产者线程首先持有生产锁
* 如果队列中元素个数等于队列容量 阻塞当前线程
* 如果队列未满将元素插入队列尾部
* 插入后元素个数小于队列容量唤醒生产线程继续插入元素
* 释放生产者锁
* 添加后队列只有一个元素 唤醒消费者消费
*/
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
// Note: convention in all put/take/etc is to preset local var
// holding count negative to indicate failure unless set.
int c = -1;
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);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
}
offer方法分析
/**
* 与put方法总体相似,支持阻塞超时
*/
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
if (e == null) throw new NullPointerException();
long nanos = unit.toNanos(timeout);
int c = -1;
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
while (count.get() == capacity) {
if (nanos <= 0)
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;
}
/**
* 该方法与put方法区别 为当队列满时直接返回而不会阻塞当前线程
*/
public boolean offer(E e) {
if (e == null) throw new NullPointerException();
final AtomicInteger count = this.count;
if (count.get() == capacity)
return false;
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
if (count.get() < capacity) {
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
}
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
return c >= 0;
}
take方法分析
/**
* 获取消费者锁如果队列为空阻塞当前消费线程
* 如果不为空出队
* 出队后队列不空唤醒消费线程继续消费
* 最后判断如果出队前队列为满唤醒生产线程继续生产
*/
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
notEmpty.await();
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
poll方法分析
/**
* 队列为空,阻塞当前消费线程支持阻塞超时
*
*/
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
E x = null;
int c = -1;
long nanos = unit.toNanos(timeout);
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
if (nanos <= 0)
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;
}
/**
* 当队列为空直接返回
*
*/
public E poll() {
final AtomicInteger count = this.count;
if (count.get() == 0)
return null;
E x = null;
int c = -1;
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
if (count.get() > 0) {
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
}
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}