
Java 发送 1000 万条短信 / 1 小时 → 线程池精准配置 + 完整代码
下面整理了生产可用、计算好参数、可直接上线的方案。
一、先算核心指标(必须先算!)
1 小时 = 3600 秒1000 万条短信 = 10,000,000QPS = 10000000 / 3600 ≈ 2778 /秒
短信接口是 IO 密集型(网络请求等待)IO 密集型公式:核心线程数 = CPU核心数 * 2(或直接 200~500,看接口响应时间)
二、最终推荐线程池配置(生产实测)
假设服务器:4核8G(最常用配置)
// 最终线程池参数
核心线程数:200
最大线程数:500
队列容量:5000
空闲保活:60s
拒绝策略:CallerRunsPolicy(保证不丢短信)三、完整可运行代码(SpringBoot + 多线程批量发送)
1. 线程池配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.*;
@Configuration
publicclass SmsThreadPoolConfig {
@Bean("smsSendExecutor")
public ExecutorService smsSendExecutor() {
// 4核8G 服务器 → 200~500 线程最稳
int corePoolSize = 200;
int maximumPoolSize = 500;
long keepAliveTime = 60L;
int queueCapacity = 5000;
returnnew ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(queueCapacity),
new ThreadFactory() {
privateint count = 0;
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("sms-send-thread-" + count++);
t.setDaemon(false);
return t;
}
},
// 重要:调用者运行,避免拒绝丢短信
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
}2. 短信发送任务类
import lombok.Data;
import java.util.List;
@Data
publicclass SmsSendTask implements Runnable {
// 每批次发 50 条(可调整)
private List<String> phoneList;
private String content;
public SmsSendTask(List<String> phoneList, String content) {
this.phoneList = phoneList;
this.content = content;
}
@Override
public void run() {
try {
for (String phone : phoneList) {
// 真实发送短信接口(你自己的业务)
sendSms(phone, content);
}
} catch (Exception e) {
// 失败重试/记录日志
e.printStackTrace();
}
}
// 短信发送接口
private void sendSms(String phone, String content) {
// 调用阿里云/腾讯云/华为云短信SDK
System.out.println("发送成功:" + phone + " 内容:" + content);
}
}3. 1000 万条发送调度(批量提交)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
@Service
publicclass SmsBatchService {
@Autowired
@Qualifier("smsSendExecutor")
private ExecutorService executorService;
/**
* 批量发送 1000 万短信
* 每 50 条一个任务
*/
public void batchSendSms() {
// 1. 从DB读取 1000 万手机号(分页查询!不要一次加载)
List<String> allPhoneList = get1000MPhonesFromDB();
// 2. 每 50 条拆分一个任务
int batchSize = 50;
List<String> taskPhones = new ArrayList<>(batchSize);
for (String phone : allPhoneList) {
taskPhones.add(phone);
if (taskPhones.size() == batchSize) {
// 提交线程池
executorService.submit(new SmsSendTask(taskPhones, "您的验证码是:888888"));
taskPhones = new ArrayList<>(batchSize);
}
}
// 最后不足50的部分
if (!taskPhones.isEmpty()) {
executorService.submit(new SmsSendTask(taskPhones, "您的验证码是:888888"));
}
}
// 模拟从数据库读取手机号(真实项目必须分页:limit 1000 循环查)
private List<String> get1000MPhonesFromDB() {
returnnew ArrayList<>();
}
}四、关键参数说明(面试/生产必懂)
1. 为什么这么配?
corePoolSize=200:IO 密集型,200 线程足够支撑 2500+ QPS
maximumPoolSize=500:峰值压力兜底
队列 5000:削峰,防止瞬间压垮
拒绝策略 CallerRunsPolicy:绝对不丢短信
2. 1000 万条 1 小时发完的关键
单线程每秒能发 10~20 条短信
200 线程 → 每秒 2000~4000 条
完全满足 2778 /秒 的需求
3. 真实生产必须注意
短信SDK必须支持异步/高并发
数据库读取必须分页(每次 1000 条)
必须加失败重试机制
必须加幂等(防止重复发送)
必须加限流(防止把短信厂商打挂)
五、总结
服务器 4核8G
核心线程:200
最大线程:500
队列:5000
每批次:50条完全可以支撑:1000万条短信 / 1小时发送完成

292

被折叠的 条评论
为什么被折叠?



