美文网首页
LinkedListBlockQueue源码分析:

LinkedListBlockQueue源码分析:

作者: 在岁月中远行 | 来源:发表于2023-02-17 02:40 被阅读0次

队列的主要操作就是存和取,每一种操作都有对应的多个API,虽然他们都可以实现元素的存和取,但是含义和处理方式是不同的,BlockQueue给出了以下几种处理方式:

抛异常  add(), remove()

返回特殊值: offer(), poll()

阻塞等待:put(), take()

超时等待:offer(E e,long timeout,TimeUnit unit) ,poll方法同左

取出元素但不移除: E peek()

源码分析:

LinkedListQueue底层使用链表结构来存储元素,元素入队后会被封装成Node节点,Node节点除了保存数据外,还有一个额外的指针next,因此它是一个单向链表的结构。

LinkedListQueue可以是有界队列,也可以是无界队列。数组的扩容是一件很麻烦的事情,因此ArrayBlockQueue必须指定容量,数组一经创建就不可变了,它只能做有界队列。而LinkedBolckQueue由于使用的是链表结构,元素的增删很容易实现,不需要初始化时就开辟内存,更适合做无界队列,默认的构造函数中,LinkedBlockQueue的容量为Integer.MAX_VALUE,可以看作是无界队列。

类图:它的继承结构和ArrayBlockQueue一样的,可以参考上篇文章。

ArrayBlockQueue使用int变量记录数量,而LinkedBlockQueue使用AtomicInteger原子类记录数量。这是因为ArrayBlockQueue生产消费使用同一把锁,任一时刻最多只有一个线程可以修改count。而LinkedBlcokQueue生产和消费使用的是不同的锁,两者线程都可以修改count,存在线程安全问题,因此使用原子类来保证数据安全。

head和last分别指向链表的首尾节点,takeLock和putLock分别是消费者和生产者竞争的锁,每把锁各自都有一个等待队列Condition,当队列满时,线程会被放入notFull等待,队列空时,线程会被放入notEmpty等待。

put 方法才是阻塞队列的核心方法,它会将元素入队,如果队列满了它会一直阻塞,直到操作成功为止。

take 方法队列的出队都是从头节点开始出队第一个节点。没有元素时会一直等待。阻塞。

相关文章

网友评论

      本文标题:LinkedListBlockQueue源码分析:

      本文链接:https://www.haomeiwen.com/subject/mdjmkdtx.html