目录一、整体设计思路二、七大核心参数 取值依据重点1. corePoolSize 核心线程数2. maximumPoolSize 最大线程数3. keepAliveTime 非核心线程空闲超时时间4. workQueue 阻塞任务队列5. threadFactory 线程工厂6. handler 拒绝策略任务满了之后如何处理7. allowCoreThreadTimeOut可选参数三、线上完整设计流程面试必答链路1. 先区分任务类型拆分线程池2. 基于机器配置初版参数3. 压测调优参数最终来源4. 监控 运维配套加分项四、面试高频追问简答五、简易生产代码示例可直接口述 / 写一、整体设计思路业务中不使用 Executors 快捷创建避免 OOM、资源耗尽手动自定义 ThreadPoolExecutor结合业务类型、任务特性、服务器配置做分层设计区分IO 密集型、CPU 密集型任务池隔离不同业务线程池避免互相影响。设计原则线程池全局单例统一管理、监控、告警核心线程、最大线程、队列、拒绝策略根据压测 线上流量调优区分业务池普通业务、异步回调、定时任务、大文件 / 长 IO 独立池增加线程名称、任务监控、异常捕获、运行状态上报二、七大核心参数 取值依据重点1.corePoolSize核心线程数含义常驻存活的线程空闲也不会回收默认。取值规则CPU 密集型计算、序列化、算法核心线程数 CPU核心数 1原因CPU 尽量打满减少上下文切换。IO 密集型数据库、RPC、Redis、文件、网络请求核心线程数 CPU核心数 * 2或CPU核心数 / (1 - 阻塞系数)阻塞系数一般取 0.8~0.9IO 等待占比高。示例8 核机器 CPU 密集819IO 密集8*2162.maximumPoolSize最大线程数含义线程池能创建的最大线程总数。触发时机核心线程全忙 任务队列已满才会新建线程直到达到最大值。取值依据结合单机压测峰值 QPS、单任务平均耗时计算 公式最大并发任务数 ≈ 峰值 QPS × 单任务耗时 (秒)受服务器负载、内存、句柄数限制不能无限放大常规经验普通业务max core * 1.5 ~ 2突发流量 / 短时高峰可适当拉大但建议不超过 100~200过多线程导致频繁切换、OOM3.keepAliveTime非核心线程空闲超时时间含义非核心线程空闲超过该时间会被回收。取值依据常规业务60sJDK 默认流量波动大、短突峰30s快速缩容低频长任务120s避免频繁创建销毁线程配合单位TimeUnit秒 / 毫秒。4.workQueue阻塞任务队列作用核心线程满了之后新任务进入队列排队。常用队列 选型场景ArrayBlockingQueue 有界队列生产首选必须设置固定容量防止无限堆积任务导致 OOM。 容量取值参考平均流量、流量毛刺经验值普通业务100~500高并发核心链路200~1000原则队列不宜过大否则流量洪峰来了线程不扩容排队严重超时。LinkedBlockingQueue 无界 / 有界不建议无界任务无限堆积必 OOM。SynchronousQueue 无容量队列来了任务直接新建线程适合极速处理、无排队场景。队列设计原则宁可触发扩容 / 拒绝也不无限排队。5.threadFactory线程工厂设计点自定义线程名线上排查日志、栈快照必备设置线程优先级、是否守护线程统一异常捕获避免任务异常导致线程消亡取值 / 设计业务池命名如order-task-pool-%d、rpc-callback-pool-%d。6.handler拒绝策略任务满了之后如何处理触发条件核心线程满 队列满 达到最大线程数新任务执行拒绝策略。 四种原生策略 生产常用改造AbortPolicy默认直接抛 RejectedExecutionException → 核心业务不推荐CallerRunsPolicy让调用者线程执行任务→ 生产最常用削峰限流、不丢任务DiscardPolicy直接丢弃新任务 → 非核心、可丢弃任务使用DiscardOldestPolicy丢弃队列最老任务 → 实时性要求高场景生产设计优先CallerRunsPolicy非核心异步任务自定义拒绝策略日志告警 落盘重试。7. allowCoreThreadTimeOut可选参数是否允许核心线程超时回收。流量极低、夜间低峰开启节约资源常态高并发关闭默认避免反复创建核心线程。三、线上完整设计流程面试必答链路1. 先区分任务类型拆分线程池不共用一个大池按业务拆分CPU 密集池计算、解析、规则校验IO 密集池DB、Redis、MQ、HTTP、RPC独立定时任务池独立延迟 / 异步回调池2. 基于机器配置初版参数以8 核 16G 服务器举例IO 密集业务池主流 corePoolSize 16 maximumPoolSize 32 queue ArrayBlockingQueue (300) keepAliveTime 60s 拒绝策略 CallerRunsPolicy3. 压测调优参数最终来源压测模拟线上峰值 QPS、慢请求、毛刺流量观测指标线程池活跃线程数、队列堆积长度任务平均耗时、P99 耗时拒绝次数、异常数、CPU / 内存负载动态微调队列持续堆满、大量拒绝 → 适当调大maxPoolSize队列长期空、线程空闲多 → 缩小core/max任务排队久、P99 高 →缩小队列容量让线程快速扩容4. 监控 运维配套加分项埋点监控核心线程数、活跃线程、队列大小、拒绝次数、任务执行耗时告警队列堆积超标、拒绝次数 0、任务超时告警动态配置部分中间件池支持 Nacos/Apollo 热更新参数无需重启服务四、面试高频追问简答为什么不用 Executors 创建newFixedThreadPool/newCachedThreadPool要么队列无界 OOM要么线程无限膨胀打垮服务器生产禁止使用。队列越大越好吗不是。队列太大线程不会扩容任务全排队响应时间陡增丧失线程池弹性。什么时候会触发拒绝策略核心线程全部忙碌 → 队列写满 → 达到最大线程数新来任务触发拒绝。CPU 密集为什么线程数不能太大线程多于 CPU 核心会造成大量上下文切换CPU 利用率反而下降。五、简易生产代码示例可直接口述 / 写// 自定义IO密集型业务线程池 private static final ThreadPoolExecutor BUSINESS_POOL new ThreadPoolExecutor( 16, // 核心线程 32, // 最大线程 60L, // 空闲超时 TimeUnit.SECONDS, new ArrayBlockingQueue(300), // 有界队列 new NamedThreadFactory(business-task-pool), // 自定义线程名 new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略 );
线程池设计 核心参数详解
目录一、整体设计思路二、七大核心参数 取值依据重点1. corePoolSize 核心线程数2. maximumPoolSize 最大线程数3. keepAliveTime 非核心线程空闲超时时间4. workQueue 阻塞任务队列5. threadFactory 线程工厂6. handler 拒绝策略任务满了之后如何处理7. allowCoreThreadTimeOut可选参数三、线上完整设计流程面试必答链路1. 先区分任务类型拆分线程池2. 基于机器配置初版参数3. 压测调优参数最终来源4. 监控 运维配套加分项四、面试高频追问简答五、简易生产代码示例可直接口述 / 写一、整体设计思路业务中不使用 Executors 快捷创建避免 OOM、资源耗尽手动自定义 ThreadPoolExecutor结合业务类型、任务特性、服务器配置做分层设计区分IO 密集型、CPU 密集型任务池隔离不同业务线程池避免互相影响。设计原则线程池全局单例统一管理、监控、告警核心线程、最大线程、队列、拒绝策略根据压测 线上流量调优区分业务池普通业务、异步回调、定时任务、大文件 / 长 IO 独立池增加线程名称、任务监控、异常捕获、运行状态上报二、七大核心参数 取值依据重点1.corePoolSize核心线程数含义常驻存活的线程空闲也不会回收默认。取值规则CPU 密集型计算、序列化、算法核心线程数 CPU核心数 1原因CPU 尽量打满减少上下文切换。IO 密集型数据库、RPC、Redis、文件、网络请求核心线程数 CPU核心数 * 2或CPU核心数 / (1 - 阻塞系数)阻塞系数一般取 0.8~0.9IO 等待占比高。示例8 核机器 CPU 密集819IO 密集8*2162.maximumPoolSize最大线程数含义线程池能创建的最大线程总数。触发时机核心线程全忙 任务队列已满才会新建线程直到达到最大值。取值依据结合单机压测峰值 QPS、单任务平均耗时计算 公式最大并发任务数 ≈ 峰值 QPS × 单任务耗时 (秒)受服务器负载、内存、句柄数限制不能无限放大常规经验普通业务max core * 1.5 ~ 2突发流量 / 短时高峰可适当拉大但建议不超过 100~200过多线程导致频繁切换、OOM3.keepAliveTime非核心线程空闲超时时间含义非核心线程空闲超过该时间会被回收。取值依据常规业务60sJDK 默认流量波动大、短突峰30s快速缩容低频长任务120s避免频繁创建销毁线程配合单位TimeUnit秒 / 毫秒。4.workQueue阻塞任务队列作用核心线程满了之后新任务进入队列排队。常用队列 选型场景ArrayBlockingQueue 有界队列生产首选必须设置固定容量防止无限堆积任务导致 OOM。 容量取值参考平均流量、流量毛刺经验值普通业务100~500高并发核心链路200~1000原则队列不宜过大否则流量洪峰来了线程不扩容排队严重超时。LinkedBlockingQueue 无界 / 有界不建议无界任务无限堆积必 OOM。SynchronousQueue 无容量队列来了任务直接新建线程适合极速处理、无排队场景。队列设计原则宁可触发扩容 / 拒绝也不无限排队。5.threadFactory线程工厂设计点自定义线程名线上排查日志、栈快照必备设置线程优先级、是否守护线程统一异常捕获避免任务异常导致线程消亡取值 / 设计业务池命名如order-task-pool-%d、rpc-callback-pool-%d。6.handler拒绝策略任务满了之后如何处理触发条件核心线程满 队列满 达到最大线程数新任务执行拒绝策略。 四种原生策略 生产常用改造AbortPolicy默认直接抛 RejectedExecutionException → 核心业务不推荐CallerRunsPolicy让调用者线程执行任务→ 生产最常用削峰限流、不丢任务DiscardPolicy直接丢弃新任务 → 非核心、可丢弃任务使用DiscardOldestPolicy丢弃队列最老任务 → 实时性要求高场景生产设计优先CallerRunsPolicy非核心异步任务自定义拒绝策略日志告警 落盘重试。7. allowCoreThreadTimeOut可选参数是否允许核心线程超时回收。流量极低、夜间低峰开启节约资源常态高并发关闭默认避免反复创建核心线程。三、线上完整设计流程面试必答链路1. 先区分任务类型拆分线程池不共用一个大池按业务拆分CPU 密集池计算、解析、规则校验IO 密集池DB、Redis、MQ、HTTP、RPC独立定时任务池独立延迟 / 异步回调池2. 基于机器配置初版参数以8 核 16G 服务器举例IO 密集业务池主流 corePoolSize 16 maximumPoolSize 32 queue ArrayBlockingQueue (300) keepAliveTime 60s 拒绝策略 CallerRunsPolicy3. 压测调优参数最终来源压测模拟线上峰值 QPS、慢请求、毛刺流量观测指标线程池活跃线程数、队列堆积长度任务平均耗时、P99 耗时拒绝次数、异常数、CPU / 内存负载动态微调队列持续堆满、大量拒绝 → 适当调大maxPoolSize队列长期空、线程空闲多 → 缩小core/max任务排队久、P99 高 →缩小队列容量让线程快速扩容4. 监控 运维配套加分项埋点监控核心线程数、活跃线程、队列大小、拒绝次数、任务执行耗时告警队列堆积超标、拒绝次数 0、任务超时告警动态配置部分中间件池支持 Nacos/Apollo 热更新参数无需重启服务四、面试高频追问简答为什么不用 Executors 创建newFixedThreadPool/newCachedThreadPool要么队列无界 OOM要么线程无限膨胀打垮服务器生产禁止使用。队列越大越好吗不是。队列太大线程不会扩容任务全排队响应时间陡增丧失线程池弹性。什么时候会触发拒绝策略核心线程全部忙碌 → 队列写满 → 达到最大线程数新来任务触发拒绝。CPU 密集为什么线程数不能太大线程多于 CPU 核心会造成大量上下文切换CPU 利用率反而下降。五、简易生产代码示例可直接口述 / 写// 自定义IO密集型业务线程池 private static final ThreadPoolExecutor BUSINESS_POOL new ThreadPoolExecutor( 16, // 核心线程 32, // 最大线程 60L, // 空闲超时 TimeUnit.SECONDS, new ArrayBlockingQueue(300), // 有界队列 new NamedThreadFactory(business-task-pool), // 自定义线程名 new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略 );