public class LinkedBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
private static final long serialVersionUID = -6903933977591709194L;
//链表节点类
static class Node<E> {
E item;
//下个节点指针
Node<E> next;
Node(E x) { item = x; }
}
/** 容量 不设置为Integer.MAX_VALUE */
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();
/**
* 唤醒等待取数据. Called only from put/offer
*/
private void signalNotEmpty() {
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
notEmpty.signal();
} finally {
takeLock.unlock();
}
}
/**
* 唤醒等待插入数据. Called only from take/poll.
*/
private void signalNotFull() {
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
notFull.signal();
} finally {
putLock.unlock();
}
}
//插入队列尾部
private void enqueue(Node<E> node) {
// assert putLock.isHeldByCurrentThread();
// assert last.next == null;
last = last.next = 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;
}
//全部上锁
void fullyLock() {
putLock.lock();
takeLock.lock();
}
//全部解锁
void fullyUnlock() {
takeLock.unlock();
putLock.unlock();
}
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();
}
}
public int size() {
return count.get();
}
//剩余容量
public int remainingCapacity() {
return capacity - count.get();
}
/**
* 插入元素到队列尾部, 当容量满时一直阻塞
*
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
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(); //已用空间加1
if (c + 1 < capacity)
notFull.signal(); //如果有剩余空间,唤醒1个取数据线程
} finally {
putLock.unlock();
}
if (c == 0) //如果队列中只有一个元素,唤醒一个取出线程
signalNotEmpty();
}
/**
* 插入元素到队列尾部, 当容量满时阻塞一段时间
*
* @return {@code true} if successful, or {@code false} if
* the specified waiting time elapses before space is available
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
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;
}
/**
* 插入元素到队列尾部
* @throws NullPointerException if the specified element is null
*/
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(); //唤醒1个插入线程
}
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty(); //唤醒取数据线程
return c >= 0;
}
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();//总数量减1
if (c > 1) //如果队列不为空
notEmpty.signal(); //唤醒1个取数据线程
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull(); //尝试唤醒插入线程线程
return x;
}
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;
}
/**
* 获取首节点元素
* @return
*/
public E peek() {
if (count.get() == 0)
return null;
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
Node<E> first = head.next;
if (first == null)
return null;
else
return first.item;
} finally {
takeLock.unlock();
}
}
}
LinkedBlockingQueue代码阅读
最新推荐文章于 2023-04-01 16:11:02 发布