小米最近在刷社招面试题,发现“ArrayBlockingQueue 和 LinkedBlockingQueue 的区别”频繁出现在面试官的题库里。
作为一名喜欢分享技术的 31 岁“老程序员”,小米觉得有必要深挖一波,顺便给大家讲讲这两位 Java 并发容器中的明星选手。毕竟,光会 API 可不够,面试官喜欢追着问底层原理!
好了,故事开始了!
起源:为什么需要阻塞队列?
某一天,小米在公司加班,产品经理老王突然跑来:“小米,我们的任务队列经常出错,你看看咋回事?”
小米打开日志一看,原来是有些线程在消费任务的时候队列为空,导致 NullPointerException,而生产者又可能突然暴增,导致 OutOfMemoryError。
于是,小米一拍脑袋:“这就是典型的生产者-消费者问题,用阻塞队列就能解决! ”
阻塞队列的作用:
- 生产者-消费者模型:生产者不断往队列里放数据,消费者不断从队列取数据,生产快了队列会阻塞生产者,消费慢了队列会阻塞消费者,保证了流量的平稳。
- 线程间通信:不需要使用 synchronized 和 wait/notify,内部已经封装好了锁机制,简化多线程编程。
- 防止过载:队列可以设置容量上限,防止生产过快导致 OOM。
java.util.concurrent 包里提供了多个阻塞队列,今天我们重点讲解ArrayBlockingQueue 和 LinkedBlockingQueue,它们是面试中最常考的两位“老大哥”。
ArrayBlockingQueue:数组实现的有界队列
基本特点:
- 基于数组,底层是 Object[],容量固定(有界队列)。
- FIFO(先进先出) ,头部取数据,尾部插入数据。
- 数据结构简单,内存占用低,适合高性能场景。
- 单一 ReentrantLock 进行并发控制,锁粒度大,生产和消费不能同时进行。
源码解析:
ArrayBlockingQueue 面试核心点
- 容量固定,创建时必须指定大小,不能动态扩容。
- 性能较高,但由于采用单一锁,并发能力稍差。
- 数据存放在数组中,适合元素数量稳定的场景,避免频繁扩容带来的开销。
LinkedBlockingQueue:链表实现的有界/无界队列
基本特点:
- 基于链表,底层是 Node 链表,可以是有界队列(指定大小)或无界队列(默认 Integer.MAX_VALUE) 。
- FIFO(先进先出) ,头部取数据,尾部插入数据。
- 双锁机制,生产和消费使用不同的 ReentrantLock,并发能力更强。
- 适合吞吐量要求较高的场景,但链表结构可能增加 GC 压力。
源码解析:
LinkedBlockingQueue 面试核心点
- 默认无界,但可以指定大小,防止 OOM。
- 性能更高,采用双锁机制,生产者和消费者可以并行执行。
- 数据存放在链表中,适合元素数量不确定的场景,但链表结构可能增加内存开销和 GC 压力。
场景对比:哪种更适合你的项目?
总结选择指南:
- 数据量稳定,低延迟需求,选 ArrayBlockingQueue(如高频交易系统)。
- 数据量不确定,吞吐量高,选 LinkedBlockingQueue(如日志收集、任务队列)。
- 避免无界 LinkedBlockingQueue,否则可能导致 OOM。
面试真题实战
面试题 1:你会怎么选择 ArrayBlockingQueue 和 LinkedBlockingQueue?
答:
- 数据量稳定,需要高性能:ArrayBlockingQueue
- 数据量不确定,需要高吞吐:LinkedBlockingQueue
- 防止 OOM,使用 LinkedBlockingQueue 时务必指定容量
面试题 2:为什么 LinkedBlockingQueue 并发能力比 ArrayBlockingQueue 强?
答:
- LinkedBlockingQueue 采用双锁机制(生产者和消费者各有一把锁),生产和消费可并行。
- ArrayBlockingQueue 采用单锁机制,生产和消费不能并行,导致并发能力稍逊。
总结
今天,我们通过小米的面试经历,深入解析了 ArrayBlockingQueue 和 LinkedBlockingQueue。面试官爱问的点,我们都帮大家整理好了!
核心记住三点:
- 固定容量 vs 可扩展性:ArrayBlockingQueue 容量固定,LinkedBlockingQueue 可以无界。
- 单锁 vs 双锁:LinkedBlockingQueue 并发能力更强。
- 适用场景不同:ArrayBlockingQueue 适合高性能场景,LinkedBlockingQueue 适合高吞吐量场景。
END
希望这篇文章能帮助你在面试时稳拿 offer!如果觉得有用,记得点个赞+在看哦!
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!