ngQueue相比能够增加并发性能
有个奇怪的地方:都使用锁了,为什么记录元素数量count却使用原子类呢?
这是由于两把锁,作用于入队与出队的操作,入队与出队也可能并发执行,同时修改count,因此要使用原子类保证修改数量的原子性
在初始化时需要设置容量大小,否则会设置成无界的阻塞队列(容量是int的最大值)
当消费速度小于生产速度时,阻塞队列中会堆积任务,进而导致容易发生OOM
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 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中存储的是旧值
c = count.getAndIncrement();
//如果数量没满 唤醒生产者
if (c + 1 < capacity)
notFull.signal();
} finally {
//解锁
putLock.unlock();
}
//如果旧值为0 说明该入队操作前是空队列,唤醒消费者来消费
if (c == 0)
signalNotEmpty();
return true;
}
入队操作类似,只不过在此期间如果数量没满唤醒生产者生产,队列为空唤醒消费者来消费,从而增加并发性能
入队只是改变指向关系
//添加节点到末尾
private void enqueue(Node<E> node) {
last = last.next = node;
}
唤醒消费者前要先获取锁
private void signalNotEmpty() {
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
notEmpty.signal();
} finally {
takeLock.unlock();
}
}
出队操作也类似
public E poll(long timeout, Ti