阻塞队列之LinkedBlockingQueue - 源码解析(一)

一、概述

LinkedBlockingQueue是一个单向链表的阻塞队列,FIFO队列,是无界队列,当前如果初始化的时候指定大小,也可以是有界队列。

二、思想

LinkedBlockingQueue思想:

  1. 数据结构是单向链表,同时维护一个头节点head和尾节点last
  2. 生产者和消费者使用同一个队列
  3. 生产者和消费者分别使用自己的锁,读写分离,生产者使用putLock,消费者使用takeLock
  4. 生产者只有在队列未满时生产,队列满时生产者线程就进行阻塞
  5. 消费者只有在队列有数据时消费,队列没有数据消费者线程就进行阻塞

三、源码解析

构造函数

默认是无界队列

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);
}

生产入队

put(E 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;
    // lockInterruptibly这个是可以响应线程中断的锁
    putLock.lockInterruptibly();
    try {
   
        // 如果队列当前数量和容量相等,说明已经满了,就阻塞等待
        while (count.get() == capacity) {
   
            notFull.await();
        }
        // 在队列链表尾部添加元素FIFO
        enqueue(node);
        // 队列当前数量+1,并将变动前的队列数量赋值给c
        c = count.getAndIncrement();
        // 如果队列还没有满,就唤醒通知入队阻塞的线程可以生产
        if (c + 1 < capacity)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值