首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >阿里二面:1000万条短信1小时发完,线程池怎么配?

阿里二面:1000万条短信1小时发完,线程池怎么配?

作者头像
程序员小猿
发布2026-05-13 20:22:00
发布2026-05-13 20:22:00
1330
举报

Java 发送 1000 万条短信 / 1 小时 → 线程池精准配置 + 完整代码

下面整理了生产可用、计算好参数、可直接上线的方案。

一、先算核心指标(必须先算!)

1 小时 = 3600 秒1000 万条短信 = 10,000,000QPS = 10000000 / 3600 ≈ 2778 /秒

短信接口是 IO 密集型(网络请求等待)IO 密集型公式:核心线程数 = CPU核心数 * 2(或直接 200~500,看接口响应时间)

二、最终推荐线程池配置(生产实测)

假设服务器:4核8G(最常用配置)

代码语言:javascript
复制
// 最终线程池参数
核心线程数:200
最大线程数:500
队列容量:5000
空闲保活:60s
拒绝策略:CallerRunsPolicy(保证不丢短信)

三、完整可运行代码(SpringBoot + 多线程批量发送)

1. 线程池配置类

代码语言:javascript
复制
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. 短信发送任务类

代码语言:javascript
复制
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 万条发送调度(批量提交)

代码语言:javascript
复制
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. 真实生产必须注意

  1. 短信SDK必须支持异步/高并发
  2. 数据库读取必须分页(每次 1000 条)
  3. 必须加失败重试机制
  4. 必须加幂等(防止重复发送)
  5. 必须加限流(防止把短信厂商打挂)

五、总结

服务器 4核8G

代码语言:javascript
复制
核心线程:200
最大线程:500
队列:5000
每批次:50条

完全可以支撑:1000万条短信 / 1小时发送完成

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-05-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程IT圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java 发送 1000 万条短信 / 1 小时 → 线程池精准配置 + 完整代码
    • 一、先算核心指标(必须先算!)
    • 二、最终推荐线程池配置(生产实测)
  • 三、完整可运行代码(SpringBoot + 多线程批量发送)
    • 1. 线程池配置类
    • 2. 短信发送任务类
    • 3. 1000 万条发送调度(批量提交)
  • 四、关键参数说明(面试/生产必懂)
    • 1. 为什么这么配?
    • 2. 1000 万条 1 小时发完的关键
    • 3. 真实生产必须注意
  • 五、总结
    • 服务器 4核8G
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档