资讯动态

spring内置线程池用法

发布时间:2026/8/14 1:25:59 来源:尧图企业网站定制
生产线程池疑问生产最近出现一些mq堆积事情分析代码发现mq消费内部还使用了spring内置线程池。但生产上只配置了spring.task.execution.thread.pool.core-size16原以为核心线程数是16但实际日志发现只到task-8然后加日志打印线程池相关属性if (configNacos.getBoolean(thread.log.debug, true)) { log.info(活跃线程:{}, 池大小:{},coresize:{} queue:{} remaincapi{}, threadPoolExecutor.getActiveCount(), threadPoolExecutor.getPoolSize(),threadPoolExecutor.getCorePoolSize(), threadPoolExecutor.getQueue().size(), threadPoolExecutor.getQueue().remainingCapacity()); }生产日志才发现coresize是8后面说明原因队列是无限大的Integer.MAX_VALUE)居然一直在生产跑着...幸好也没发生OOM任务基本都执行了。活跃线程:7, 池大小:8,coresize:8 queue:0 remaincapi2147483647 ----生产一条日志示例从日志看当前等待队列的线程为0个剩余队列容量是 2147483647恰好就是Integer.MAX_VALUE。说明队列是无限大的。需要补充最大线程数队列数和拒绝策略的配置线程池配置# 核心线程数保持 16 spring.task.execution.pool.core-size16 # 最大线程数建议设置为一个合理的数字比如 CPU 核数的 2-4 倍或根据业务压测结果设定如果不设置就是INT.MAX_VALUE spring.task.execution.pool.max-size50 # 任务队列容量建议设置一个合理的上限防止无限制积压,如果不设置就是INT.MAX_VALUE spring.task.execution.pool.queue-capacity200 # 线程名前缀方便排查 spring.task.execution.thread-name-prefixsign-task- # 拒绝策略 当队列满了的时候新任务采取什么策略具体后面列出 spring.task.execution.pool.rejection-policyCallerRunsPolicy # 线程空闲多久被回收默认60秒 spring.task.execution.pool.keep-alive60但核心线程数这个生产设置的时候写错属性值了spring.task.execution.thread.pool.core-size16 这个是错误的不生效使用了spring默认的核心线程数是8根据 ThreadPoolExecutor 的工作规则只有当任务队列满了之后才会创建超出核心线程数默认8的新线程。而未配置队列容量的队列容量几乎是无限的所以任务会无限堆积当 8 个核心线程都被占满后所有新来的任务都会成功进入这个无边界的队列等待既不会创建新线程也不会触发任何拒绝策略。内存被耗尽这个队列会像一个无底洞不断吞噬提交过来的任务。随着任务越积越多内存占用持续飙升最终导致 OutOfMemoryError应用崩溃。拒绝策略为什么会触发拒绝策略触发拒绝策略意味着你的线程池已经达到最大承载能力当线程池中的线程数达到max-size并且任务队列 (queue-capacity) 也已满此时再有新任务提交就会触发拒绝策略。因此为了能让拒绝策略生效你需要先为max-size和queue-capacity设置一个具体、合理的数值。否则如果队列容量是无限大默认任务只会无限堆积而永远不会触发拒绝策略最终导致内存溢出OOM。如何选择对于大多数业务系统CallerRunsPolicy是兼顾安全与稳定的首选。它确保了任务不会丢失同时通过让调用线程“慢下来”的方式反向保护了整个应用。选择AbortPolicy则更适合那些需要你主动捕获异常并执行降级逻辑的场景线程回收业务高峰时可能线程数创建到了max-size当业务低峰时大部分线程可能都是空闲的就会被回收。当线程数超过核心线程数core-size后多余的空闲线程是会被回收的最终线程池会收缩回你设置的核心线程数。这个“回收”行为是由keep-alive默认60秒这个配置项控制的

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价