LinkedBlockingQueue 源码分析-新增和删除
新增
put 方法,把 e 新增到队列的尾部,如果有可以新增的空间的话,直接新增成功,否则当前线程陷入等待,源码:
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
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();
}
private void enqueue(Node<E> node) {
last = last.next = node;
}
复制代码
if (e == null) throw new NullPointerException();
如果 e 为空,则抛出异常
int c = -1;
预先设置 c 为 -1,如果负数为则会新增失败
while (count.get() == capacity) { }
队列满了则线程阻塞,等待其他线程的唤醒(其他线程 take 成功后就会唤醒此处被阻塞的线程,await 无限等待
enqueue(node);
队列没有满,直接新增到队列的尾部
c = count.getAndIncrement();
新增计数赋值
if (c + 1 < capacity)
如果链表现在的大小 小于链表的容量,说明队列未满,尝试唤醒一个 put 的等待线程
if (c == 0) signalNotEmpty();
c==0,代表队列里面有一个元素,尝试唤醒一个 take 的等待线程
删除
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;
}
private E dequeue() {
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;
}
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();
}
}
private E dequeue() {
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;
}
复制代码
int c = -1;
默认负数,代表失败
final AtomicInteger count = this.count;
count 代表当前链表数据的真实大小
while (count.get() == 0) { notEmpty.await(); }
空队列时,阻塞,等待其他线程唤醒
x = dequeue();
非空队列,从队列的头部拿一个出来
if (c > 1) notEmpty.signal();
如果队列里面有值,从 take 的等待线程里面唤醒
if (c == capacity) signalNotFull();
如果队列空闲还剩下一个,尝试从 put 的等待线程中唤醒
评论