LinkedBlockingQueue源码

LinkedBlockingQueue源码

LinkedBlockingQueue介绍

【1】LinkedBlockingQueue是一个基于链表实现的阻塞队列,默认情况下,该阻塞队列的大小为Integer.MAX_VALUE,由于这个数值特别大,所以 LinkedBlockingQueue 也被称作无界队列,代表它几乎没有界限,队列可以随着元素的添加而动态增长,但是如果没有剩余内存,则队列将抛出OOM错误。所以为了避免队列过大造成机器负载或者内存爆满的情况出现,我们在自定义线程池使用到LinkedBlockingQueue队列时会根据业务需求定义合适的队列容量值capacity。

【2】LinkedBlockingQueue内部由单链表实现,只能从head取元素,从tail添加元素。LinkedBlockingQueue采用两把锁的锁分离技术实现入队出队互不阻塞,分别是写锁putLock和读锁takeLock。添加元素和获取元素都有独立的锁,也就是说LinkedBlockingQueue是读写分离的,读写操作可以并行执行。

LinkedBlockingQueue类的一些关键特性和方法

  • 无界队列:如果没有指定容量,队列的容量默认为 Integer.MAX_VALUE。
  • 线程安全:通过内部锁机制确保了线程安全。
  • FIFO 顺序:元素按照先进先出的方式进行排列。
  • 条件对象:使用 ReentrantLock 和 Condition 对象来控制队列的入队和出队操作。
  • 动态创建节点:每次插入操作时,除非这会使队列超出其容量,否则都会动态创建新的链表节点。
  • 序列化:该类是可序列化的,这意味着它可以被写入到一个输出流中,并从输入流中恢复。
  • 迭代器:提供了弱一致性迭代器,用于按顺序访问队列中的元素。
  • Spliterator:提供了一个 Spliterator,支持在并行操作中使用 Stream API。

LinkedBlockingQueue使用

//创建有界队列,指定队列的大小为100
BlockingQueue<Runnable> boundedQueue = new LinkedBlockingQueue<>(100);
//无界队列
BlockingQueue<Runnable> unboundedQueue = new LinkedBlockingQueue<>();

LinkedBlockingQueue源码介绍

1.属性值

// 表示队列的容量上限,如果不指定容量值,则为Integer.MAX_VALUE,无限大
private final int capacity;
// 当前队列的元素数量 使用AtomicInteger来实现线程安全的计数器
private final AtomicInteger count = new AtomicInteger();
// 链表的头节点,其item属性总是null,用于标识队列的开始
transient Node<E> head;
// 链表的尾节点,总是指向最后一个节点,其next属性为null
private transient Node<E> last;
// 读锁 控制从队列中取出元素操作
private final ReentrantLock takeLock = new ReentrantLock();
// notEmpty:takeLock的条件对象
// 当拿到takeLock锁并且notEmpty条件对象条件成立也就是队列至少有一条可取数据的时候,才会从队列取出一个元素。
// 拿到takeLock锁,但是队列无元素时,线程会调用notEmpty条件对象的wait方法,这将导致线程释放锁并进入WAITING状态,等待其他线程的唤醒。(注意,offer()方法是非阻塞的,从队列中获取不到数据会返回false)
private final Condition notEmpty = takeLock.newCondition();
// 写锁 控制往队列中添加元素操作
private final ReentrantLock putLock = new ReentrantLock();
// notFull条件
// 当队列满了时,put锁会会阻塞在notFull上,等待其它线程唤醒
// 当拿到putLock锁并且notFull条件对象条件成立也就是队列未满(通过AutomicInteger记录的队列状态来判断当前队列元素数量是否大于队列容量阈值,小于则表示未满),才会往队列中添加元素。
private final Condition notFull = putLock.newCondition();

// 典型的单链表结构
// Node类是一个泛型类,可以存储任何类型的元素(由类型参数E指定)。
static class Node<E> {
    E item;  // 存储节点中的数据项
    Node<E> next;  // 单链表结构 指向链表中的下一个节点,有三种可能的值:
    			    // 1.真实的后继节点。
				   // 2.this Node,这通常意味着后继是head.next,这可能是在初始化时或者在某些特殊情况下使用。
				   // 3.null,表示没有后继节点,即当前节点是链表的最后一个节点。
    Node(E x) { item = x; } // 有参构造函数
}

2.构造器

public LinkedBlockingQueue() {
    // 如果没传容量,就使用最大int值初始化其容量
    this(Integer.MAX_VALUE);
}

public LinkedBlockingQueue(int capacity) {
    if (capacity <= 0) throw new IllegalArgumentException();
    this.capacity = capacity;
    // 初始化head和last指针为空值节点
    last = head = new Node<E>(null);
}

// TaskQueue队列才会使用到这个有参够咱
// 这是构造器的声明,它接受一个Collection类型的参数c,该参数中的元素类型是E的子类型。
public LinkedBlockingQueue(Collection<? extends E> c) {
    // 调用LinkedBlockingQueue的另一个有参构造器,将队列的容量设置为Integer.MAX_VALUE&#
  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值