Java线程池知识小结
一、线程池
线程池 = 存放多个线程的 “池子”。程序需要执行任务时,直接从池子里借一个线程;任务执行完,线程不销毁,放回池子复用。
线程池的作用:
- 避免频繁创建 / 销毁线程(非常耗资源)
- 控制并发线程数量(防止服务器卡死)
- 统一管理线程(监控、调优、拒绝策略)
线程池 = 线程复用 + 控制并发 + 资源管理
Java 内置线程池的核心工具:
ExecutorService—— 线程池接口ThreadPoolExecutor—— 线程池真正实现类(最常用)
二、线程池 7 大核心参数
new ThreadPoolExecutor( int corePoolSize, // 核心线程数(常驻线程) int maximumPoolSize, // 最大线程数 long keepAliveTime, // 非核心线程空闲多久被销毁 TimeUnit unit, // 时间单位 BlockingQueue<Runnable> workQueue, // 任务队列 ThreadFactory threadFactory, // 线程工厂(命名线程) RejectedExecutionHandler handler // 拒绝策略 )执行流程(超级重要)
- 任务进来 → 核心线程未满 → 创建核心线程执行
- 核心线程满了 → 任务放进队列排队
- 队列满了 → 创建非核心线程执行
- 总线程达到最大 → 执行拒绝策略
三、最常用的 4 种线程池(简单好用)
Java 通过Executors工具类快速创建:
1.FixedThreadPool(固定线程数)
适合:已知并发压力的任务
ExecutorService pool = Executors.newFixedThreadPool(5);2. CachedThreadPool(自动扩容)
适合:大量短生命周期任务
ExecutorService pool = Executors.newCachedThreadPool();3.ScheduledThreadPool(定时任务)
适合:定时、周期性执行任务
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);4.SingleThreadExecutor(单线程)
适合:需要顺序执行的任务
ExecutorService pool = Executors.newSingleThreadExecutor();四、拒绝策略(线程满了怎么办)
4 种内置策略:
- AbortPolicy(默认):直接抛异常
- CallerRunsPolicy:让提交任务的线程自己执行
- DiscardPolicy:直接丢掉任务
- DiscardOldestPolicy:丢掉队列最老的任务
真实开发常用:CallerRunsPolicy(最安全)
五、线程池大小如何设置?
- CPU 密集型:
核心数 + 1 - IO 密集型:
核心数 * 2或更多(因为 IO 会等待)
例:4 核 CPU
- 计算任务 → 核心线程 5
- 网络 / 数据库 → 核心线程 8~10
六、生产环境最佳线程池配置
1. 核心原则
禁止Executors快捷创建,直接手动ThreadPoolExecutor实例化,规避 OOM 风险;按业务类型区分线程池,隔离任务互不影响。
2. 参数取值规范
| 参数 | IO 密集型 | CPU 密集型 | 说明 |
|---|---|---|---|
| 核心线程 | CPU 核数 ×2 | CPU 核数 + 1 | 常驻核心,保障基础吞吐 |
| 最大线程 | 核心 ×4 | 等于核心 | IO 可扩容应对突发峰值 |
| 空闲存活 | 60s | 0s | 闲置线程及时回收,节省资源 |
| 阻塞队列 | ArrayBlockingQueue(200) | 固定队列 100 | 有界队列,杜绝无限堆积 OOM |
| 线程工厂 | 自定义命名 | 自定义命名 | 便于日志排查问题 |
| 拒绝策略 | CallerRunsPolicy | CallerRunsPolicy | 不丢任务,降级由调用方执行 |
3. 队列选型
- ArrayBlockingQueue:有界队列,固定容量,生产首选,可控内存
- 禁用
SynchronousQueue、无界LinkedBlockingQueue,极易引发内存溢出
4. 拒绝策略选型
生产首选CallerRunsPolicy
- 优势:不会丢弃业务任务,削峰限流保护服务
- 禁用默认 AbortPolicy 频繁抛异常、Discard 系列丢失数据
5. 生产运维要点
- 线程池拆分:业务、定时、异步消息各自独立池,避免互相阻塞
- 监控埋点:监控线程活跃数、队列积压、拒绝次数、执行耗时
- 优雅关闭:应用下线调用
shutdown(),等待任务收尾 - 动态调参:压测后根据实际 QPS、耗时微调核心数与队列大小
6. 避坑总结
- 不使用 Executors 创建线程池
- 队列必须设固定上限
- 业务分类隔离线程池
- 自定义线程名,方便问题定位
- 拒绝策略优先调用者执行,保障数据不丢失
