尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Spring为什么不建议使用默认线程池?
大家好我是Java1234_小锋。很多同学在项目里一写异步就随手Async或者直接Executors.newFixedThreadPool(...)感觉“能跑就行”。上线跑一段时间后机器内存飙高、线程数爆表、接口偶发卡死——回头一看问题往往出在默认线程池上。这篇文章用比较白话的方式把“为什么不建议用默认线程池、正确该怎么配”讲清楚并给几段能直接改的代码。一、先搞清楚Spring里的“默认线程池”指什么在 Spring 项目里大家说的“默认线程池”通常有两类Async没指定执行器时Spring 会落到SimpleAsyncTaskExecutor来一个任务就新建一个线程用完就丢几乎不做复用。JDK 的Executors工厂方法比如Executors.newFixedThreadPool(n)、newCachedThreadPool()。看起来方便但队列或线程数往往是“无限”的埋了隐患。这两种都能“先跑起来”但生产环境风险都偏大。二、默认线程池到底有什么坑1. 线程创建太猛机器扛不住SimpleAsyncTaskExecutor不复用线程。流量一上来线程越开越多上下文切换变多CPU 空转每个线程都占栈内存堆外压力跟着涨极端情况下直接把机器打挂2. 队列无限膨胀容易 OOMExecutors.newFixedThreadPool(10)内部用的是无界队列LinkedBlockingQueue不设容量。核心线程忙不过来时任务会一直往队列里塞内存一点点被吃光最后可能直接OutOfMemoryError。3. 拒绝策略、超时、监控都不好控默认方案通常缺这些“安全带”队列满了怎么办拒绝策略线程空闲多久回收线程叫什么名字出问题不好排查当前活跃数、队列积压怎么看生产里一旦出故障你会发现默认线程池又快又省事排查起来却处处别扭。三、一个常见翻车现场下面这段代码很常见本地测几个请求完全没问题ServicepublicclassOrderService{/** * 异步发送订单通知未指定线程池 */AsyncpublicvoidsendOrderNotice(LongorderId){// 模拟耗时操作调短信、推送、写日志等try{Thread.sleep(200);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}System.out.println(通知已发送, orderIdorderId, threadThread.currentThread().getName());}}再配上最简开启ConfigurationEnableAsyncpublicclassAsyncConfig{// 什么都不配就用默认执行器}高峰期如果一下子进来几千个订单通知Spring 会不断创建新线程。短时间看“好像更快了”过一会儿线程数和内存就开始报警。再看另一种“看起来很专业”的写法/** * 不推荐使用 Executors 创建默认风格线程池 */publicclassBadPoolExample{// 固定 10 个线程但任务队列是无界的privatefinalExecutorServiceexecutorExecutors.newFixedThreadPool(10);publicvoidhandle(Runnabletask){executor.submit(task);}}线程数是固定的但队列能无限增长——这正是很多线上 OOM 的源头。四、推荐做法自己配一个可控的线程池更稳妥的方式是显式声明ThreadPoolTaskExecutor把核心参数都写明白。packagecom.example.config;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.scheduling.annotation.EnableAsync;importorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;importjava.util.concurrent.Executor;importjava.util.concurrent.ThreadPoolExecutor;/** * 异步线程池配置 * 说明给 Async 指定可预期、可监控的线程池避免使用默认执行器 */ConfigurationEnableAsyncpublicclassAsyncConfig{/** * 业务异步线程池 * 参数需要结合机器核数和任务类型微调 */Bean(namebizExecutor)publicExecutorbizExecutor(){ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();// 核心线程数常驻线程executor.setCorePoolSize(8);// 最大线程数高峰时可扩容到的上限executor.setMaxPoolSize(16);// 有界队列防止任务无限堆积导致 OOMexecutor.setQueueCapacity(200);// 空闲线程存活时间秒executor.setKeepAliveSeconds(60);// 线程名前缀方便日志排查executor.setThreadNamePrefix(biz-async-);// 队列满时的拒绝策略由调用线程执行起到背压作用executor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy());// 项目关闭时等待任务完成避免直接中断executor.setWaitForTasksToCompleteOnShutdown(true);executor.setAwaitTerminationSeconds(30);executor.initialize();returnexecutor;}}业务里这样用ServicepublicclassOrderService{/** * 指定自定义线程池避免落到默认执行器 */Async(bizExecutor)publicvoidsendOrderNotice(LongorderId){// 业务逻辑...}}如果不用Async也可以直接注入使用ServicepublicclassReportService{privatefinalExecutorbizExecutor;publicReportService(Qualifier(bizExecutor)ExecutorbizExecutor){this.bizExecutorbizExecutor;}/** * 手动提交异步任务 */publicvoidexportAsync(StringreportId){bizExecutor.execute(()-{// 导出报表...System.out.println(导出完成: reportId);});}}几个实用建议IO 密集调外部接口、读写线程数可以略多一点CPU 密集计算、压缩线程数别盲目开大接近 CPU 核数更稳队列一定要有界并想清楚拒绝策略线程名加前缀出问题翻日志会轻松很多五、异步任务执行流程对照图用流程图把“默认”和“自定义”两条路对比一下否是否是业务方法触发异步任务是否指定自定义线程池?使用 SimpleAsyncTaskExecutor每个任务新建线程流量升高后线程暴增CPU飙高 / 内存告警使用 ThreadPoolTaskExecutor有界队列 固定线程复用队列是否已满?任务入队等待执行触发拒绝策略如 CallerRunsPolicy工作线程复用执行资源可控、便于排查再补一张“参数怎么协作”的简图是否是否是否新任务到来当前线程数小于 corePoolSize?创建核心线程执行队列是否还有空位?任务进入有界队列线程数小于 maxPoolSize?创建临时线程执行执行拒绝策略看懂这两张图基本就明白为什么“能跑”不等于“能扛”。六、写在最后Spring 不建议用默认线程池不是矫情而是默认方案优先保证“方便启动”并不优先保证“线上稳健”。记住三句话就够用了别裸用Async给它指定自己的线程池别用Executors图省事尤其小心无界队列把核心数、队列、拒绝策略写清楚让系统在高峰时有“刹车”异步能力本身没错错的是把生产流量交给一套“看不见边界”的默认配置。把线程池管起来很多线上玄学问题会少一大半。
RELATED

相关推荐

Vue3专题 - 列表渲染

Vue3专题 - 列表渲染

大家好,我是Java1234_小锋老师,最近更新 《一天学会 Vue3 Vite element-plus UI框架 视频教程》专辑,感谢大家支持。 本课程主要介绍和讲解 Vue3框架,Vite构建工具,以及element-plus UI框架。Vue3核心知识介绍&…

📅 2026/9/24 15:53:00
11_比较排序去重函数

11_比较排序去重函数

比较函数 np.any() 至少有一个元素满足指定条件,就返回Truenp.all() 所有的元素都满足指定条件,才返回True 排序函数 array1.sort();不写 axis 时,默认 axis1,也就是按行内部原地排序;np.sort()&#xff1a…

📅 2026/9/15 15:07:02
npj Biofilms and Microbiomes期刊文章:发现肠肺调控通路,云克隆亚精胺ELISA 试剂盒助力机制研究

npj Biofilms and Microbiomes期刊文章:发现肠肺调控通路,云克隆亚精胺ELISA 试剂盒助力机制研究

过敏性哮喘长期缺少根源性治疗手段,肠肺轴上下游分子链条很难完整闭环,本篇 2026 年7月刊发于《npj Biofilms and Microbiomes》的研究论文围绕这一问题展开研究。来自中国疾病预防控制中心传染病预防控制所的研究团队完整解析「肉桂酸 - STAT1-SAT1 - 亚…

📅 2026/8/29 19:19:17
MORE NEWS

更多资讯

📰

Yii2 REST 响应格式化指南:Content Negotiation、Serializer 与 JSON/XML 输出控制

后端Web框架 【免费下载链接】yii2 Yii 2: The Fast, Secure and Professional PHP Framework 项目地址: https://gitcode.com/gh_mirrors/yi/yii2 点击查看 免费下载 RESTful API 请求处理中,响应格式化决定客户端最终收到的数据形态:资源对…

📰

Kubernetes 云原生可观察性(Observability)实践指南:指标、日志与追踪三大支柱详解

Kubernetes 云原生可观察性(Observability)实践指南:指标、日志与追踪三大支柱详解 【免费下载链接】kubernetes-handbook Kubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南 项目地址: https://gitcode.com/gh_mirr…

📰

embassy-net-wiznet 0.3.0 演进解读:WIZnet SPI 以太网驱动的多芯片支持与中断寄存器重构

嵌入式物联网异步编程 【免费下载链接】embassy Modern embedded framework, using Rust and async. 项目地址: https://gitcode.com/gh_mirrors/em/embassy 点击查看 免费下载 本文围绕 embassy-net-wiznet 驱动 crate 的版本演进记录(即 embassy-net-…

📰

云手机原理与 Python 自动化实战:ADB 单机到百台群控,附傲晨云手机选型建议

摘要:云手机不是“模拟器上云”这么简单,它的本质是把 Android 实例资源化。本文先讲清云手机的 ARM 虚拟化、容器隔离、ADB 控制通道、WebRTC 推流四大件,再用 Python 演示单机装包/启动/截图、UI 自动化、批量并发群控,最后结合…

📰

Ceph test_orchestrator 模块实战指南:用模拟数据驱动 ceph orch 编排器开发与集成测试

存储分布式文件系统对象存储后端高可用 【免费下载链接】ceph Ceph is a distributed object, block, and file storage platform 项目地址: https://gitcode.com/gh_mirrors/ce/ceph 点击查看 免费下载 test_orchestrator 是 Ceph Manager(mgr&#x…

📰

南航双中台实践:业务中台与数据中台如何驱动数字化转型

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬