跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
Javajava算法

Java 并发包 LinkedBlockingQueue 详解

综述由AI生成Java 并发包中基于链表实现的阻塞队列 LinkedBlockingQueue。介绍其双锁机制、内部数据结构(哨兵节点)、核心方法(put/take/offer/poll)及线程安全原理。对比了与 ArrayBlockingQueue 和 ConcurrentLinkedQueue 的差异,并指出适用场景为生产者 - 消费者模型及线程池任务队列,同时提醒注意无界队列的内存风险。

并发大师发布于 2026/3/26更新于 2026/5/920 浏览
Java 并发包 LinkedBlockingQueue 详解

一、概述

LinkedBlockingQueue 是 Java 并发包(java.util.concurrent)中基于链表实现的阻塞队列,支持可选容量限制(默认无界),通过 双锁机制(ReentrantLock)和 条件变量(Condition)实现线程安全。其核心设计目标是高吞吐量和生产者 - 消费者模型的高效协作。

关键特性
  1. 线程安全:通过分离的 putLock(入队锁)和 takeLock(出队锁)实现并发控制,减少锁竞争。
  2. 阻塞操作:put() 和 take() 方法在队列满或空时自动阻塞,支持超时等待。
  3. FIFO 顺序:严格遵循先进先出原则。
  4. 可选容量:构造时可指定最大容量(有界),默认无界(Integer.MAX_VALUE)。
  5. 弱一致性迭代器:遍历时可能看到部分更新,但不会抛出 ConcurrentModificationException。

二、内部数据结构

1. 节点类 Node<E>
static class Node<E> {
    E item; // 存储元素
    Node<E> next; // 指向下一个节点
    Node(E x) { item = x; }
}
  • 链表结构:通过 head(头节点)和 last(尾节点)维护队列顺序。
  • 哨兵节点:初始化时 head 和 last 均指向一个 item=null 的哨兵节点,简化边界处理。
2. 核心属性
属性作用
capacity队列最大容量(默认 Integer.MAX_VALUE)
count当前元素数量(AtomicInteger 保证原子性)
putLock/takeLock入队和出队操作的独占锁
notEmpty/notFull条件变量,分别用于队列空和队列满时的线程阻塞与唤醒

三、核心方法与实现原理

1. 入队操作
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); final ReentrantLock putLock = this.putLock; final AtomicInteger count = this.count; putLock.lockInterruptibly(); // 获取入队锁 try { while (count.get() == capacity) { notFull.await(); // 队列满时阻塞 } enqueue(node); // 入队操作 c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); // 唤醒其他生产者线程 } finally { putLock.unlock(); } if (c == 0) signalNotEmpty(); // 若队列之前为空,唤醒消费者线程 }
  • 阻塞逻辑:队列满时调用 notFull.await(),释放锁并等待。
  • 唤醒机制:入队成功后,若队列未满,通过 notFull.signal() 唤醒其他生产者线程。
offer(E e)
public boolean offer(E e) {
    if (e == null) throw new NullPointerException();
    final AtomicInteger count = this.count;
    if (count.get() == capacity) return false; // 非阻塞,直接返回失败
    int c = -1;
    Node<E> node = new Node<>(e);
    final ReentrantLock putLock = this.putLock;
    putLock.lock();
    try {
        if (count.get() < capacity) {
            enqueue(node);
            c = count.getAndIncrement();
            if (c + 1 < capacity) notFull.signal();
        }
    } finally {
        putLock.unlock();
    }
    if (c == 0) signalNotEmpty();
    return c >= 0;
}
  • 非阻塞特性:队列满时立即返回 false,不阻塞线程。

2. 出队操作
take()
public E take() throws InterruptedException {
    E x;
    int c = -1;
    final AtomicInteger count = this.count;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lockInterruptibly(); // 获取出队锁
    try {
        while (count.get() == 0) {
            notEmpty.await(); // 队列空时阻塞
        }
        x = dequeue(); // 出队操作
        c = count.getAndDecrement();
        if (c > 1) notEmpty.signal(); // 唤醒其他消费者线程
    } finally {
        takeLock.unlock();
    }
    if (c == capacity) signalNotFull(); // 若队列之前满,唤醒生产者线程
    return x;
}
  • 阻塞逻辑:队列空时调用 notEmpty.await(),释放锁并等待。
  • 唤醒机制:出队成功后,若队列非空,通过 notEmpty.signal() 唤醒其他消费者线程。
poll()
public E poll() {
    final AtomicInteger count = this.count;
    if (count.get() == 0) return null; // 非阻塞,直接返回 null
    E x = null;
    int c = -1;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lock();
    try {
        if (count.get() > 0) {
            x = dequeue();
            c = count.getAndDecrement();
            if (c > 1) notEmpty.signal();
        }
    } finally {
        takeLock.unlock();
    }
    if (c == capacity) signalNotFull();
    return x;
}
  • 非阻塞特性:队列空时立即返回 null,不阻塞线程。

四、线程安全与锁机制

1. 双锁分离
  • putLock:控制入队操作,允许多个生产者并发插入。
  • takeLock:控制出队操作,允许多个消费者并发移除。
  • 优势:减少锁竞争,提升吞吐量(相比单锁的 ArrayBlockingQueue)。
2. 条件变量
  • notEmpty:队列空时,消费者线程在此条件上等待。
  • notFull:队列满时,生产者线程在此条件上等待。
  • 唤醒策略:插入或移除元素后,通过 signal() 或 signalAll() 唤醒等待线程。

五、适用场景

  1. 生产者 - 消费者模型:平衡生产者和消费者的处理速度,避免资源浪费。
  2. 线程池任务队列:如 ThreadPoolExecutor 默认使用 LinkedBlockingQueue 作为任务缓冲区。
  3. 数据流水线处理:在多阶段数据处理中传递数据。
  4. 限流场景:通过设置容量限制防止系统过载。

六、与其他队列的对比

特性LinkedBlockingQueueArrayBlockingQueueConcurrentLinkedQueue
线程安全机制双锁分离单锁(ReentrantLock)CAS + 自旋
容量可选有界(默认无界)必须有界无界
性能高并发下吞吐量高低并发下延迟低读多写少场景更优
适用场景生产者 - 消费者、任务队列固定容量缓冲区高并发无锁队列

七、注意事项

  1. 内存风险:默认无界队列可能导致内存溢出(OOM),建议生产环境指定容量。
  2. 中断处理:阻塞方法(如 put()/take())会响应中断,需捕获 InterruptedException 并处理中断状态。
  3. 性能调优:高并发场景下,合理设置队列容量和线程池参数(如 corePoolSize、maximumPoolSize)。

八、源码设计细节

  1. 哨兵节点:初始化时 head 和 last 均指向空节点,简化插入和删除逻辑。
  2. 弱一致性迭代器:遍历时基于当前快照,允许并发修改但可能遗漏新元素。
  3. 内存管理:节点通过 new 分配,依赖 GC 回收,避免手动内存管理开销。

九、总结

LinkedBlockingQueue 是 Java 并发编程中高性能阻塞队列的典范,通过双锁分离和条件变量机制,在保证线程安全的同时最大化吞吐量。适用于生产者 - 消费者模型、线程池任务队列等场景,但需注意无界队列的内存风险。理解其底层实现(如双锁、条件变量)有助于在实际工程中合理应用。

目录

  1. 一、概述
  2. 关键特性
  3. 二、内部数据结构
  4. 1. 节点类 Node<E>
  5. 2. 核心属性
  6. 三、核心方法与实现原理
  7. 1. 入队操作
  8. put(E e)
  9. offer(E e)
  10. 2. 出队操作
  11. take()
  12. poll()
  13. 四、线程安全与锁机制
  14. 1. 双锁分离
  15. 2. 条件变量
  16. 五、适用场景
  17. 六、与其他队列的对比
  18. 七、注意事项
  19. 八、源码设计细节
  20. 九、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 宇树 G1 机器人基于 FAST-LIO 的建图与配置实战
  • OpenBioLLM-Llama3 医疗大模型安装与应用指南
  • BK7258 对接 LiveKit WebRTC:端侧适配全流程
  • Python NumPy 入门指南:数据处理与科学计算基础
  • LangChain 实战:工具调用与结构化输出
  • C++ 基于正倒排索引的 Boost 搜索引擎 Searcher 模块实现详解
  • Llama 3.1 开源模型快速部署指南
  • Llama-Factory 训练进度条卡住排查与优化指南
  • 越疆机器人 TCP 通讯 12 点标定脚本程序
  • 基于 LLaMA-Factory 的大模型 LoRA 微调实战指南
  • 【Mac 实战】简单知识图谱搭建步骤详解(Neo4j + py2neo)
  • 卷积神经网络(CNN)深度解析:理论、实现与应用
  • Lada v0.10.1 本地 AI 视频去马赛克工具使用指南
  • Python 转行指南:爬虫、数据分析与 Web 开发入门路径
  • 数学建模竞赛全流程指南与 AI 提示词
  • Z-Image-Turbo AI 绘画教学环境一键部署实战指南
  • AI 思维解析:从感知到决策的核心逻辑
  • Webots 2025a 与 ROS 2 Jazzy e-puck 机器人集成实战
  • TensorRT 镜像与推理优化实战指南
  • Linux 内存管理:zram 技术详解与实战指南

相关免费在线工具

  • 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