跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

Java 中的 ConcurrentLinkedQueue 详解

Java 并发包中的 ConcurrentLinkedQueue 是无界非阻塞线程安全队列,基于单向链表和 CAS 操作实现。其特点包括无界性、非阻塞、无锁设计、FIFO 顺序及弱一致性迭代器。核心原理涉及 head/tail 指针管理、自旋重试及松弛不变量。适用于高并发生产者 - 消费者模型及低延迟系统,但需注意 size() 性能问题及内存风险。相比 LinkedBlockingQueue,它吞吐量更高但不支持阻塞操作。

鲜活发布于 2026/3/23更新于 2026/10/2525K 浏览
Java 中的 ConcurrentLinkedQueue 详解

概述

ConcurrentLinkedQueue 是 Java 并发包(java.util.concurrent)中提供的无界非阻塞线程安全队列,基于单向链表实现,采用 CAS(Compare-and-Swap) 操作和 无锁算法 保证并发安全。其核心设计目标是高吞吐量和低延迟,适用于高并发场景下的生产者 - 消费者模型。

关键特性

  1. 无界性:理论上容量无限,但受内存限制。
  2. 非阻塞:操作永不阻塞线程,失败立即返回(如 poll() 在队列为空时返回 null)。
  3. 无锁设计:通过 CAS 和自旋机制实现线程安全,避免传统锁的开销。
  4. FIFO 顺序:严格遵循先进先出原则。
  5. 弱一致性迭代器:遍历时可能看到部分更新,但不会抛出 ConcurrentModificationException。

内部数据结构

节点类 Node

private static class Node<E> {
    volatile E item;      // 存储元素
    volatile Node<E> next; // 指向下一个节点
    
    // CAS 操作方法
    boolean casItem(E cmp, E val) { ... }
    boolean casNext(Node<E> cmp, Node<E> val) { ... }
}
  • volatile 修饰:保证多线程可见性。
  • CAS 操作:通过 Unsafe 类实现原子性更新。

队列指针

  • head:指向队列头部(可能滞后于实际头节点)。
  • tail:指向队列尾部(可能滞后于实际尾节点)。
  • 哨兵节点:初始化时 head 和 tail 均指向一个 item=null 的哨兵节点。

核心方法与实现原理

入队操作(offer/add)

public boolean offer(E e) {
    checkNotNull(e);
    Node<E> newNode = new Node<>(e);
    for (Node<E> t = tail, p = t;;) {
        Node<E> q = p.next;
        if (q == null) {
            if (p.casNext(null, newNode)) {
                if (p != t) casTail(t, newNode);
                return true;
            }
        } else if (p == q) {
            p = (t != (t = tail)) ? t : head;
        } else {
            p = (p != t && t != (t = tail)) ? t : q;
        }
    }
}
  • CAS 竞争:多个线程可能同时尝试插入,仅一个成功。
  • tail 滞后更新:仅在 p != t 时更新 tail,减少 CAS 操作频率。

出队操作(poll)

public E poll() {
    restartFromHead:
    for (;;) {
        for (Node<E> h = head, p = h, q;;) {
            E item = p.item;
            if (item != null && p.casItem(item, null)) {
                if (p != h) updateHead(h, p);
                return item;
            } else if ((q = p.next) == null) {
                updateHead(h, p);
                return null;
            } else if (p == q) continue restartFromHead;
            else p = q;
        }
    }
}
  • CAS 移除:将头节点的 item 设为 null,延迟物理删除。
  • head 更新:若 p != h,则更新 head 指针。

其他方法

  • peek():获取头元素但不移除,逻辑与 poll() 类似,不修改 item。
  • size():遍历链表统计元素数,非线程安全(高并发下结果可能不准确)。
  • remove(Object o):遍历链表移除首个匹配元素,返回是否成功。

无锁并发控制机制

CAS 操作

  • 原子性更新:通过 Unsafe.compareAndSwapObject 实现对 item 和 next 的原子修改。
  • 自旋重试:CAS 失败时循环重试,而非阻塞线程。

松弛不变量(Relaxed Invariants)

  • head 滞后:可能指向已删除节点,仅在必要时更新(如遍历时遇到自引用节点)。
  • tail 滞后:减少更新频率,提升吞吐量。

自引用节点

  • 标记删除:出队后,原头节点的 next 指向自身,防止其他线程误用。
  • 垃圾回收:物理删除由 GC 处理,避免频繁内存操作。

适用场景

  1. 高并发生产者 - 消费者模型:如日志处理、实时事件分发。
  2. 低延迟系统:如高频交易、游戏服务器。
  3. 无界缓冲需求:需动态扩展队列长度的场景。
  4. 弱一致性要求:允许短暂的数据不一致(如遍历时)。

与 LinkedBlockingQueue 对比

特性ConcurrentLinkedQueueLinkedBlockingQueue
线程安全机制CAS 无锁锁(ReentrantLock)
容量限制无界可选有界/无界
阻塞操作无支持 put()/take()
吞吐量高中等
内存占用节点结构更轻量可能更高

最佳实践

  1. 避免频繁调用 size():高并发下性能差,建议通过外部计数器统计。
  2. 合理预估容量:虽无界,但内存耗尽可能引发 OOM。
  3. 结合其他同步机制:如需精确控制,可与 Semaphore 或 CountDownLatch 联用。
  4. 弱一致性遍历:接受遍历时可能遗漏新元素,适用于非强一致性场景。

源码设计细节

  1. 哨兵节点:初始化时 head 和 tail 指向同一个哨兵节点,简化边界条件处理。
  2. 自引用节点:出队后原头节点 next=self,标记为待回收。
  3. CAS 优化:节点构造时使用 Unsafe.putObject 替代 volatile 写操作,减少内存屏障开销。

总结

ConcurrentLinkedQueue 是 Java 并发编程中高性能无锁队列的典范,通过 CAS 和松弛不变量设计,在保证线程安全的同时最大化吞吐量。适用于对延迟敏感、无需严格容量控制的场景,但需注意其无界特性可能带来的内存风险。理解其底层机制(如 CAS、自旋、自引用节点)有助于在实际工程中合理应用。

目录

  1. 概述
  2. 关键特性
  3. 内部数据结构
  4. 节点类 Node<E>
  5. 队列指针
  6. 核心方法与实现原理
  7. 入队操作(offer/add)
  8. 出队操作(poll)
  9. 其他方法
  10. 无锁并发控制机制
  11. CAS 操作
  12. 松弛不变量(Relaxed Invariants)
  13. 自引用节点
  14. 适用场景
  15. 与 LinkedBlockingQueue 对比
  16. 最佳实践
  17. 源码设计细节
  18. 总结

更多推荐文章

查看全部
  • WebView 并发初始化竞争风险分析
  • AI 测试技术详解:自动化框架、缺陷检测与 A/B 测试优化
  • ClawPanel v4.4.0 来了:AI 助手浮窗 + 非 OpenAI 模型兼容性修复
  • VSCode 远程连接时 Copilot Chat 图标不显示修复方案
  • 下一代无障碍交互架构:Web MCP 微核多态与本地优先 SaaS 设计
  • C++ 继承机制详解:概念、访问权限与默认成员函数
  • React 基础:JSX 语法细节与表单组件实战
  • JavaScript 设计模式:策略模式实战案例解析
  • YOLO11 基于 DroneVehicle 数据集的无人机视角车辆目标检测
  • Elasticsearch 进阶实战:JavaRestClient 操作索引与文档及海量数据批处理指南
  • PySLAM 视觉定位库:Python 环境搭建与核心功能解析
  • Llama-2-7B 在昇腾 NPU 上的性能测评与部署实践
  • 《Agent Runtime 工程化》第十一章 源码研读方法:11.11 验收标准
  • 应对互联网寒冬:Android开发者如何提升自我
  • 常见降低AIGC检测率工具对比与选择指南
  • Java 常见集合框架详解
  • C++ STL 容器与 Qt 容器对比及选型建议
  • C++ 继承进阶:友元、静态成员与菱形继承底层逻辑
  • Spring Boot 实战:基于 WebSocket 的前后端实时匹配系统实现
  • Spring Cloud 微服务环境与工程搭建指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online