Java线程池是多线程编程中的核心组件,能够有效管理线程资源、提升系统性能。
一、为什么需要线程池?
- 降低资源消耗:避免频繁创建/销毁线程的开销
- 提高响应速度:任务到达时直接使用可用线程
- 统一管理:控制并发数量,避免资源耗尽
- 提供扩展性:支持任务队列、拒绝策略等灵活配置
二、核心实现类 ThreadPoolExecutor
//线程池三种常见的分类,三者底层都是通过new ThreadPoolExecutors()来实现的
public class ThreadPoolDemo1{
public static void main(String[] args) {
//1. 一池5线程
ExecutorService threadPool1 = Executors.newFixedThreadPool(5);
//2. 一池一线程
ExecutorService threadPool2 = Executors.newSingleThreadExecutor();
//3. 一池可扩容线程
ExecutorService threadPool3 = Executors.newCachedThreadPool();
try{
for (int i = 0; i < 10; i++) {
threadPool1.execute(() -> {
System.out.println(Thread.currentThread().getName() + "办理业务");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭线程池(不关闭的话,程序一直运行下去)
threadPool1.shutdown();
}
}
}
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler
)
核心参数解析
参数 | 说明 |
---|---|
corePoolSize | 核心线程数(长期保留的线程) |
maximumPoolSize | 最大线程数(包括核心线程和非核心线程) |
keepAliveTime | 非核心线程的空闲存活时间 |
unit | 时间单位(TimeUnit.SECONDS等) |
workQueue | 任务队列(BlockingQueue实现) |
threadFactory | 线程创建工厂(可自定义线程名称、优先级等) |
handler | 拒绝策略(当队列和线程池满时的处理策略) |
三、线程池工作流程
- 提交任务时,优先使用核心线程执行
- 核心线程已满 → 任务进入阻塞队列等待
- 队列已满 → 创建非核心线程执行任务(直到达到最大线程数)
- 超过最大线程数 → 触发拒绝策略
四、拒绝策略(RejectedExecutionHandler)
- AbortPolicy(默认):抛出
RejectedExecutionException
- CallerRunsPolicy:由提交任务的线程直接执行
- DiscardPolicy:静默丢弃被拒绝的任务
- DiscardOldestPolicy:丢弃队列中最旧的任务,重试提交当前任务
// 自定义拒绝策略示例
new ThreadPoolExecutor.AbortPolicy() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 自定义处理逻辑
}
}
五、Executors工具类预定义线程池
方法 | 特点 | 潜在问题 |
---|---|---|
newFixedThreadPool | 固定线程数,无界队列 | 可能堆积大量任务导致OOM |
newCachedThreadPool | 线程数无限制(60秒回收),适合短时异步任务 | 可能创建过多线程导致资源耗尽 |
newSingleThreadExecutor | 单线程,保证任务顺序执行 | 无界队列有OOM风险 |
newScheduledThreadPool | 支持定时/周期性任务 | 复杂任务需谨慎使用 |
建议:生产环境推荐手动配置
ThreadPoolExecutor
参数
//自定义线程池
public class ThreadPoolDemo2 {
public static void main(String[] args) {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
2,
5,
1L,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
//线程池的默认的工厂
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy()
);
}
}
六、线程池状态管理
- RUNNING:接受新任务,处理队列任务
- SHUTDOWN:不接受新任务,继续处理队列任务
- STOP:不接受新任务,不处理队列任务,中断进行中的任务
- TIDYING:所有任务终止,workerCount=0
- TERMINATED:terminated()方法执行完成
// 关闭线程池的正确方式
executor.shutdown(); // 优雅关闭
executor.shutdownNow(); // 立即中断(慎用)
七、最佳实践
- 合理配置参数
- CPU密集型任务:corePoolSize = CPU核心数
- IO密集型任务:corePoolSize = CPU核心数 * 2
- 使用有界队列(如
ArrayBlockingQueue
)避免OOM - 自定义线程名称(通过ThreadFactory)方便问题排查
- 监控线程池状态(通过重写beforeExecute/afterExecute)
- 处理未捕获异常
executor.setRejectedExecutionHandler((r, e) ->
System.out.println("Task rejected: " + r));
八、常见问题
- 线程泄漏:忘记关闭线程池 → 使用
try-with-resources
或finally
块 - 任务堆积:合理设置队列容量和拒绝策略
- 上下文切换开销:避免过度配置线程数