千万级推送不仅考参数调优更考架构防御本文拆解 1000 万短信 1 小时发完的真实现场从 黄金公式到动态监控调优再到防止 OOM 的“生产级”拒绝策略。文末附带 P7 级面试套路模板助你扫平线程池深坑。写在开头前两天有个在大厂搬砖的兄弟找我吐槽说面试挂在了“线程池”上。面试官没问那些死记硬背的原理直接抛了一个业务题“我们要发 618 营销短信1000 万条要求 1 小时内发完。你打算怎么设计线程池核心参数给多少拒绝策略选哪个”这哥们想都没想“简单啊算一下 1 小时 3600 秒每秒发 2800 条。直接搞个 FixedThreadPool线程数开到 500队列给大点不就行了”面试官冷笑一声连追三问“FixedThreadPool 默认队列是 LinkedBlockingQueue长度是 Integer.MAX_VALUE千万级数据还没发完内存就 OOM 了你负责”“如果短信网关限流了你的任务积压在队列里应用重启任务全丢了怎么办”“你怎么证明你配的线程数是最优的是拍脑袋想的还是有数据支撑”他瞬间原地石化。其实这道题考的是“高并发下的资源掌控力”。今天 Fox带你拆解线程池的 3 种实战境界。一、 为什么 Executors是生产环境的“禁区”在大厂规范里严禁使用 Executors.newFixedThreadPool 或 newCachedThreadPool。OOM 隐患默认的无界队列能塞 个任务。在 1000 万数据的冲击下还没等到线程处理你的 JVM 堆内存就先爆了。资源耗尽CachedThreadPool 允许创建的线程数也是无限大瞬间的高并发能直接把 CPU 100% 跑满。Fox的结论生产环境必须手动创建 ThreadPoolExecutor且必须配合有界队列。二、 核心架构线程池调优的 3 种境界境界 1利用“黄金公式”计算初始值面试官问你线程数给多少千万别直接说 200 或 500。你要先问“这任务是 CPU 密集型还是 IO 密集型”短信推送涉及网络调用属于典型的IO 密集型。根据经验公式CPU 核心数目标 CPU 利用率等待时间与计算时间的比值实战落地对于千万级推送通常 W/C 很大建议初始线程数设置为 起步并根据压测调整。境界 2动态调优 全链路监控参数是“死”的流量是“活”的。大厂 P7 的标准做法是动态线程池。参数动态化核心参数CoreSize、MaxSize、QueueSize不要写死在代码里接入配置中心如 Apollo、Nacos。监控预警监控队列剩余容量、线程池活跃度。当队列超过 80% 满时自动触发告警或动态扩容。Fox 提示业内著名的开源项目 Hippo4J 或 DynamicTp 就是干这个的面试时提一句加分不少。3. 境界 3拒绝策略的“终极防线”当 1000 万数据涌入线程池满了拒绝策略RejectedExecutionHandler选哪个AbortPolicy默认直接抛异常千万别选数据直接丢了。CallerRunsPolicy推荐让提交任务的线程比如主线程自己去执行。 这其实是一种“天然的背压Backpressure”。主线程去发短信了它就没空再去数据库捞新任务从而减缓了任务产生速度给线程池喘息的机会。很多同学应该还记得我写过CallerRunsPolicy回退给调用者执行是个坑因为它会阻塞主线程。但是在千万级推送这种“离线批量场景”下这个“坑”反而成了神技。在线 Web 场景避坑如果是处理用户请求绝对不能用它否则 Tomcat 线程被占满整个网站直接卡死。离线批量场景神器我们从 DB 里捞千万级数据往线程池塞。如果池子满了触发 CallerRunsPolicy让“捞数据的线程”自己去发短信。高阶奥义天然背压Backpressure。当“生产者”被迫去干“消费者”的活儿时它就没空去 DB 捞新数据了。这会自动减缓任务产生的速度给线程池喘息的时间彻底规避 OOM 风险。三、 最后的“防杠”指南万一服务挂了怎么办面试官看你答得不错通常会祭出最后一招“任务在内存队列里机器宕机了100 万条短信没发出去怎么补救”满分回答本地持久化在任务入队前先在数据库/Redis 记录一个“发送中”的状态。Ack 机制线程处理完后回调更新状态为“已完成”。离线补偿启动一个定时任务TN专门扫描那些处于“发送中”超过 10 分钟的任务重新投递。四、 面试标准答案模板直接背诵“针对 1000 万短信推送我不会使用 Executors 快捷创建因为无界队列有 OOM 风险。第一参数设置我会基于公式进行压测由于是 IO 密集型初始线程数设为 。第二拒绝策略我会选择 CallerRunsPolicy。它能通过‘背压’机制让主线程在任务过载时参与处理从而限制任务的生产速度保证系统不崩。第三动态化为了应对短信网关波动我会接入动态线程池框架实时监控队列积压情况并动态调整核心线程。第四可靠性结合数据库状态位和定时补偿任务确保即便机器重启任务也不会丢失。”五、 进阶思考单机扛住了那“分布式”呢聊到这里肯定有兄弟会问“Fox单机线程池调优我懂了但如果 1000 万任务发到一半机器宕机了怎么办如果是 1 亿数据单机带宽和 CPU 根本吃不下呢”这正是大厂面试官最喜欢的“夺命连环炮”。 在真实的生产环境下我们绝对不会把鸡蛋放在一个篮子里。单机调优是“术”集群架构才是“道”。现在的互动问题来了面试官追问 “现在给你 5 台机器组成的集群你如何设计一套架构保证这 1000 万条短信在 1 小时内 ‘不重复、不遗漏、高并发’ 地发出去”提示几个思考维度任务分片5 台机器怎么分工才不会抢任务状态流转机器挂了剩下的任务怎么接管全局控速怎么保证 5 台机器加起来不把供应商的网关冲垮写在最后技术面试拼的从不是死记硬背的参数而是你对「系统稳定性」的敬畏之心。能提前预判OOM风险、考虑到背压问题、兼顾数据可靠性这才是你和普通开发者拉开差距的关键。