Java并发工具:ConcurrentLinkedQueue

Java并发工具:ConcurrentLinkedQueue

编码文章call10242025-06-21 17:57:014A+A-

ConcurrentLinkedQueue 是 Java 并发包中基于无锁算法实现的高性能线程安全无界队列,属于 java.util.concurrent 包。它基于链表结构实现,并且适用于高并发场景下的先进先出(FIFO)操作。

核心特性

  • 无锁设计

采用 CAS(Compare-And-Swap)操作实现线程安全,避免了传统锁机制的性能瓶颈,减少线程阻塞。

  • 非阻塞队列

所有操作(如入队、出队)均不会因锁竞争导致线程挂起,适合高吞吐量场景。

  • 无界队列

动态扩展链表节点,理论上容量仅受内存限制。

  • FIFO 顺序

遵循先进先出原则,元素从头部移除、尾部插入。

  • 单向链表结构

内部由 Node 节点构成单向链表,头尾节点(head、tail)通过 volatile 修饰保证可见性。

实现原理

  • 数据结构

每个 Node 包含 volatile 修饰的 item(元素)和 next(后继节点指针)。

初始化时头尾节点指向同一个空节点,后续操作中头尾更新可能延迟。

  • 入队(offer 方法)

CAS 操作尾部插入:新元素追加到链表尾部,通过 CAS 更新尾节点 tail。若 CAS 失败则重试,直至成功。

延迟更新尾节点:并非每次插入都更新 tail,减少 CAS 竞争,提升性能。

  • 出队(poll 方法)

CAS 操作头部移除:从头部节点获取元素,通过 CAS 将头节点 item 置为 null,并移动 head 指针。

协助清理逻辑:若发现其他线程未完成的出队操作,会协助完成以维持队列状态一致性。

常用方法

add(E e)

将元素插入队列尾部,成功返回 true,如果由于容量限制导致失败则抛出异常(但因为是无界队列,通常不会失败)。

offer(E e)

将元素插入队列尾部,总是返回 true(因为是无界队列)。

poll()

获取并移除队列头部元素;如果队列为空,则返回 null。

peek()

获取但不移除队列头部元素;如果队列为空,则返回 null。

size()

返回当前队列中的元素数量(注意:不是实时精确值)。

isEmpty()

判断队列是否为空(弱一致性判断)。

与其他队列对比

队列类型

是否阻塞

是否线程安全

是否支持 null

特点

ConcurrentLinkedQueue

非阻塞、高性能、弱一致性

LinkedList

单线程适用

ArrayBlockingQueue

有界、阻塞、性能略低

LinkedBlockingQueue

可配置阻塞行为

PriorityQueue

优先级排序,非线程安全

DelayQueue

延迟获取元素

适用场景

  • 高并发读写

如电商系统中的购物车操作、实时日志处理等,需保证数据一致性与低延迟。

  • 无界数据流转

适用于生产者速率不可控但需高效处理的场景(如消息队列中间件)。

注意事项

  • 遍历弱一致性

迭代器可能反映队列某一时刻的快照,不保证实时性。

  • 慎用 size() 方法

遍历链表计算元素数量,时间复杂度为 O(n),高并发下性能较差。

  • 不能放入 null 值

如果调用 offer(null) 或 add(null),会抛出 NullPointerException。

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4