news 2026/4/19 22:59:43

字节二面挂了!被问“1000 万短信 1 小时发完,怎么设计线程池?”

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
字节二面挂了!被问“1000 万短信 1 小时发完,怎么设计线程池?”
千万级推送不仅考参数调优,更考架构防御!本文拆解 1000 万短信 1 小时发完的真实现场:从 黄金公式,到 动态监控调优,再到防止 OOM 的 “生产级”拒绝策略。文末附带 P7 级面试套路模板,助你扫平 线程池深坑。

“我们要发 618 营销短信,1000 万条,要求 1 小时内发完。你打算怎么设计线程池?核心参数给多少?拒绝策略选哪个?”

结果你想都没想:“简单啊,算一下 1 小时 3600 秒,每秒发 2800 条。直接搞个FixedThreadPool,线程数开到 500,队列给大点不就行了?”

我冷笑一声,连追三问:

  1. FixedThreadPool默认队列是LinkedBlockingQueue,长度是Integer.MAX_VALUE,千万级数据还没发完,内存就 OOM 了,怎么办?”
  2. “如果短信网关限流了,你的任务积压在队列里,应用重启任务全丢了怎么办?”
  3. “你怎么证明你配的线程数是最优的?是拍脑袋想的,还是有数据支撑?”

第一点:

在大厂规范里,严禁使用Executors.newFixedThreadPoolnewCachedThreadPool

  • OOM 隐患:默认的无界队列能塞 个任务。在 1000 万数据的冲击下,还没等到线程处理,你的 JVM 堆内存就先爆了。
  • 资源耗尽:CachedThreadPool允许创建的线程数也是无限大,瞬间的高并发能直接把 CPU 100% 跑满。

所以生产环境必须手动创建ThreadPoolExecutor,且必须配合有界队列

线程池调优的三种修为:

修为 1:利用“黄金公式”计算初始值

面试官问你线程数给多少,千万别直接说 200 或 500。你要先问:“这任务是 CPU 密集型还是 IO 密集型?”

短信推送涉及网络调用,属于典型的IO 密集型

根据经验公式:

N(cpu):CPU 核心数

U(cpu):目标 CPU 利用率

W/C:等待时间与计算时间的比值

实战落地:对于千万级推送,通常 W/C 很大,建议初始线程数设置为 起步,并根据压测调整。

修为 2:动态调优 + 全链路监控

参数是“死”的,流量是“活”的。大厂 P7 的标准做法是:动态线程池

  1. 参数动态化:核心参数(CoreSize、MaxSize、QueueSize)不要写死在代码里,接入配置中心(如 Apollo、Nacos)。
  2. 监控预警:监控队列剩余容量、线程池活跃度。当队列超过 80% 满时,自动触发告警或动态扩容。

Fox 提示:业内著名的开源项目 Hippo4J 或 DynamicTp 就是干这个的,面试时提一句加分不少。

修为 3:拒绝策略的“终极防线”

当 1000 万数据涌入,线程池满了,拒绝策略选哪个?

  • AbortPolicy(默认):直接抛异常,千万别选,数据直接丢了。
  • CallerRunsPolicy(推荐):让提交任务的线程(比如主线程)自己去执行。 这其实是一种“天然的背压”。主线程去发短信了,它就没空再去数据库捞新任务,从而减缓了任务产生速度,给线程池喘息的机会。

很多同学应该还记得我写过:CallerRunsPolicy(回退给调用者执行)是个坑,因为它会阻塞主线程。但是!在千万级推送这种“离线批量场景”下,这个“坑”反而成了神技。

  • 在线 Web 场景(避坑):如果是处理用户请求,绝对不能用它,否则 Tomcat 线程被占满,整个网站直接卡死。
  • 离线批量场景(神器):我们从 DB 里捞千万级数据往线程池塞。如果池子满了,触发CallerRunsPolicy,让“捞数据的线程”自己去发短信。
  • 高阶奥义:天然背压(Backpressure)。当“生产者”被迫去干“消费者”的活儿时,它就没空去 DB 捞新数据了。这会自动减缓任务产生的速度,给线程池喘息的时间,彻底规避 OOM 风险。

三、 最后的“防杠”指南:万一服务挂了怎么办?

面试官看你答得不错,通常会祭出最后一招:“任务在内存队列里,机器宕机了,100 万条短信没发出去,怎么补救?”

  1. 本地持久化:在任务入队前,先在数据库/Redis 记录一个“发送中”的状态。
  2. Ack 机制:线程处理完后,回调更新状态为“已完成”。
  3. 离线补偿:启动一个定时任务(T+N),专门扫描那些处于“发送中”超过 10 分钟的任务,重新投递。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 22:58:38

【3D视觉实战】ShapeNet数据集:从核心结构到语义扩展的完整指南

1. ShapeNet数据集全景解析 第一次接触ShapeNet时,我被这个庞然大物吓到了——超过300万个3D模型,涵盖上千个物体类别,这哪是数据集,简直是3D视觉界的"百科全书"。但真正用起来才发现,它的精妙之处在于模块化…

作者头像 李华
网站建设 2026/4/19 22:57:25

智能音源配置实战:5步搭建专业级音乐资源库

智能音源配置实战:5步搭建专业级音乐资源库 【免费下载链接】LXMusic音源 lxmusic(洛雪音乐)全网最新最全音源 项目地址: https://gitcode.com/guoyue2010/lxmusic- LXMusic音源配置是音乐爱好者的核心需求,这款智能音源工…

作者头像 李华
网站建设 2026/4/19 22:56:21

StarUML插件DDL实战:5分钟搞定ER图到MySQL建表脚本(含Java代码生成)

StarUML插件DDL实战:5分钟搞定ER图到MySQL建表脚本(含Java代码生成) 在数据库设计领域,效率往往决定着项目推进的速度。想象一下这样的场景:产品经理刚刚确认完需求,开发团队需要在两小时内完成数据库设计并…

作者头像 李华
网站建设 2026/4/19 22:52:47

从FGM到FreeLB:一次讲透对抗训练怎么“卷”起来的(附代码避坑指南)

对抗训练算法演进:从FGM到FreeLB的实战解析与避坑指南 对抗训练作为提升模型鲁棒性的关键技术,近年来在自然语言处理领域掀起了一轮又一轮的"内卷"浪潮。本文将带您深入剖析FGM、PGD和FreeLB三大经典算法的设计哲学与实现细节,通过…

作者头像 李华