展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

LinkedBlockingQueue使用及源码分析

  • 简介
在并发编程中,LinkedBlockingQueue使用的非常频繁。因其可以作为生产者消费者的中间商
add() 实际上调用的是offer,区别是在队列满的时候,add会报异常
offer() 对列如果满了,直接入队失败
put("111") 在队列满的时候,会进入阻塞的状态
remove() 直接调用poll,唯一的区别即使remove会抛出异常,而poll在队列为空的时候直接返回null
poll() 在队列为空的时候直接返回null
take() 在队列为空的时候,会进入等待的状态
  • 案例1
public class Demo2 {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingQueue<String> strings = new LinkedBlockingQueue<>();
//往队列里存元素
strings.add("111");
strings.offer("111");
strings.put("111");
//从队列中取元素
String remove = strings.remove();
strings.poll();
strings.take();
}
}
  • add方法源码
# 查看add方法
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
# 查看offer方法
boolean offer(E e);

public boolean offer(E e) {
if (e == null) throw new NullPointerException(); // 判断是否为null,为null则抛出异常
final AtomicInteger count = this.count; // 获取当前队列的元素个数
if (count.get() == capacity) // 是否是最大容量
return false;
final int c;
final Node<E> node = new Node<E>(e); // new 1个Node
final ReentrantLock putLock = this.putLock; // 获取到锁,并打开锁
putLock.lock();
try {
if (count.get() == capacity) // 如果当前队列的个数小于容量
return false;
enqueue(node); // 则执行入队
c = count.getAndIncrement(); // 自增后
if (c + 1 < capacity) // 队列还没满时
notFull.signal(); // 随机唤醒1个线程
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
return true;
}
# 查看Node
static class Node<E> {
E item; // 当前元素
/**
* One of:
* - the real successor Node
* - this Node, meaning the successor is head.next
* - null, meaning there is no successor (this is the last node)
*/
Node<E> next; // 下一个元素
Node(E x) { item = x; }
}
# 查看如对方法,把元素添加到队列末尾
private void enqueue(Node<E> node) {
// assert putLock.isHeldByCurrentThread();
// assert last.next == null;
last = last.next = node;
}
  • 查看put方法源码
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException(); // 判断是否为null
final int c;
final Node<E> node = new Node<E>(e); // 获取Node
final ReentrantLock putLock = this.putLock; // 获取锁
final AtomicInteger count = this.count; // 获取队列元素个数
putLock.lockInterruptibly();
try {
/*
* Note that count is used in wait guard even though it is
* not protected by lock. This works because count can
* only decrease at this point (all other puts are shut
* out by lock), and we (or some other waiting put) are
* signalled if it ever changes from capacity. Similarly
* for all other uses of count in other wait guards.
*/
while (count.get() == capacity) { // 如果队列中元素等于最大容量
notFull.await(); // 队列挂起
}
enqueue(node); // 入队
c = count.getAndIncrement(); // 自增
if (c + 1 < capacity) // 队列数量小于最大容量,随机唤醒1个线程
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty(); // 唤醒所有等待线程
}
  • 查看remove方法
public E remove() {
E x = poll();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
# 查看poll实现
E poll();

public E poll() {
final AtomicInteger count = this.count; // 获取队列中元素个数
if (count.get() == 0)
return null;
final E x;
final int c;
final ReentrantLock takeLock = this.takeLock; // 获取锁
takeLock.lock();
try {
if (count.get() == 0) // 若队列中有数据
return null;
x = dequeue(); // 执行dequeue方法
c = count.getAndDecrement(); // 自减
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock(); // 释放锁
}
if (c == capacity)
signalNotFull(); // 唤醒所有等待线程
return x;
}
# 查看dequeue方法:将头节点移除,将下一个节点作为头节点
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;
}
  • 查看take源码
public E take() throws InterruptedException {
final E x;
final int c;
final AtomicInteger count = this.count; // 获取队列中元素个数
final ReentrantLock takeLock = this.takeLock; // 获取锁
takeLock.lockInterruptibly();
try {
while (count.get() == 0) { // 队列中元素个数为0
notEmpty.await(); // 阻塞队列,阻止线程去队列中取元素
}
x = dequeue(); // 否则出队列
c = count.getAndDecrement(); // 自减
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
posted @   DogLeftover  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示