11小节:实现阻塞队列容量热更新策略
作者:程序员马丁
热门项目实战社群,收获国内众多知名公司面试青睐,近千名同学面试成功!助力你在校招或社招上拿个offer。
实现阻塞队列容量热更新策略,元数据信息:
- 什么是线程池oneThread:https://t.zsxq.com/5GfrN
- 代码仓库:https://gitcode.net/nageoffer/onethread —— 申请项目权限参考上述线程池项目链接
- 章节难度:★★☆☆☆ - 中等
- 视频地址:本章节内容简单,无
©版权所有 - 拿个offer-开源&项目实战星球专属学习项目,依据《中华人民共和国著作权法实施条例》和《知识星球产权保护》,严禁未经本项目原作者明确书面授权擅自分享至 GitHub、Gitee 等任何开放平台。违者将面临法律追究。
内容摘要:在日常开发中,我们常通过调整线程池参数来优化系统性能,然而你是否遇到过这样的场景:线程池任务堆积、队列打满,却无法重启服务,只想临时调大队列容量以缓解压力?本篇文章将聚焦于阻塞队列容量为何不能动态调整,以及我们该如何优雅地实现一套支持运行时 热更新容量的阻塞队列方案。
课程目录如下所示:
- 业务说明
- 如何实现阻塞队列热更新?
- 文末总结
业务说明
1. 什么是队列?
队列是一种遵循 先进先出(FIFO) 规则的线性数据结构:元素只能从“队尾”入队、在“队头”出队;当内部没有元素时即为空队列。凭借这一简单而强大的特性,队列在程序设计中无处不在——从线程池的任务排队到消息中间件的核心存储模型,都离不开它。
2. 什么是阻塞队列?
队列大家都不陌生,那 阻塞队列 又是什么?在 Java 中它由接口 BlockingQueue
定义,虽然名称看起来抽象,底层实现却十分灵活——可以基于数组,也可以使用单向或双向链表等结构。
与普通队列相比,阻塞队列多了两项关键能力:
- 阻塞插入:当队列已满时,执行
put
的线程会被挂起,直到出现空位; - 阻塞移除:当队列为空时,执行
take
的线程同样会被挂起,直到有元素可取。
LinkedBlockingQueue
就是其中一种实现,内部采用单向链表存储元素。下面的继承关系图展示了它在 Java 并发包中的层次结构。
这里不针对阻塞队列展开具体介绍,网上的资料也挺多的,我在 21 年写过一篇 1.1w字,10图,轻松掌握BlockingQueue,推荐大家学习下。
JDK 默认提供了以下几种阻塞队列实现:
如何实现阻塞队列热更新?
1. 阻塞队列不支持更新容量
在日常线程池调优过程中,我们可能会遇到一个真实的问题:
队列被塞满了,线程池也跑满了,但我又不能轻易重启服务,只是想把队列容量调大点,临时抗一波压力,有没有办法?
如果使用的是 LinkedBlockingQueue
,可能会发现它的容量是固定的,根本不支持动态调整——这就是我们今天要讲的问题。
LinkedBlockingQueue
阻塞队列的容量是 int 类型,如果不设置容量默认是 Integer.MAX_VALUE
,设置容量后,因为字段类型是 final,是没有办法变更容量的。
public class LinkedBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
/** The capacity bound, or Integer.MAX_VALUE if none */
private final int capacity;
}