一、什么是线程池?为什么要用线程池?
线程池是一种池化技术 ,简单理解就是:提前创建一批线程,放到一个 "池子" 里统一管理,任务来了直接复用,任务执行完不销毁,继续等待下一个任务。
如果不使用线程池,每次任务都 new Thread(),会带来几个严重问题:
- 线程创建与销毁开销巨大
- 大量线程抢占 CPU,导致频繁上下文切换
- 无法控制并发量,容易 OOM
- 代码难以维护、无法统一监控
使用线程池的好处非常明显:
- 线程复用,避免频繁创建销毁
- 控制并发线程数,保护系统稳定
- 提高响应速度,任务到达直接执行
- 统一管理,方便扩展、监控、优化
所以在实际开发中,只要涉及多线程,优先使用线程池。
二、ThreadPoolExecutor 是 Java 线程池的真正实现
Java 中所有线程池,最终都指向 ThreadPoolExecutor。它的完整构造方法如下,也是面试必问的 7 大参数:
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler
)
这 7 个参数,是理解线程池的灵魂。
三、7 大参数详解(最通俗版本)
1. corePoolSize 核心线程数
常驻线程池的线程数量,即使空闲也不会被回收。类比:公司正式员工,不忙也不走。
2. maximumPoolSize 最大线程数
线程池能容纳的最大线程总数。核心线程 + 非核心线程 ≤ 最大线程数。
3. keepAliveTime 空闲线程存活时间
非核心线程空闲多久会被回收。
4. unit 时间单位
keepAliveTime 的单位:秒、毫秒、分钟。单位写错,线程池直接异常。
5. workQueue 阻塞队列
任务排队的地方。核心线程忙不过来,任务进入队列。
6. threadFactory 线程工厂
创建线程的工厂。建议自定义,设置业务线程名,方便排查问题。
7. handler 拒绝策略
队列满 + 线程数达到最大 → 触发拒绝策略。
四、线程池执行流程(最重要)
当提交一个任务,线程池执行流程如下:
- 核心线程未满 → 创建核心线程执行
- 核心线程已满 → 进入阻塞队列排队
- 队列已满 → 创建非核心线程执行
- 达到最大线程数 → 执行拒绝策略