并发编程--线程池(1)线程池概念 Java 线程池体系(Executor、ThreadPoolExecutor、Executors)
一、线程池概念
线程池(Thread Pool) 是一种 线程复用机制,用于管理和复用线程,避免频繁创建和销毁线程带来的性能开销,提高并发性能。
核心目的:
线程复用:减少线程创建和销毁开销。
控制线程数量:防止系统因线程过多而崩溃。
任务排队:线程空闲时可执行等待队列中的任务。
统一管理:方便线程管理、监控与调优。
线程池基本组成:
核心线程数(corePoolSize):线程池保持的最小线程数。
最大线程数(maximumPoolSize):线程池允许的最大线程数。
任务队列(workQueue):存放等待执行的任务。
线程工厂(ThreadFactory):用于创建新线程。
拒绝策略(RejectedExecutionHandler):当线程池和队列都满时如何处理任务。
线程存活时间(keepAliveTime):非核心线程空闲存活时间。
二、Java 线程池体系结构
Java 的线程池体系主要由 接口 + 核心实现 + 工厂类 组成。
1. Executor 体系
类型 作用 Executor(接口) 线程执行规范,只定义 execute(Runnable)
方法ExecutorService(接口,继承 Executor) 扩展接口,支持任务管理和返回结果(submit、shutdown 等) AbstractExecutorService(抽象类) 提供 ExecutorService 的部分实现,简化子类实现 ThreadPoolExecutor(核心类)推荐使用 ExecutorService 的主要实现类,可高度自定义线程池参数 Executors(工具类)不推荐使用 提供常用线程池工厂方法,封装 ThreadPoolExecutor 快速创建线程池 2. Executors 的问题(不推荐使用)
不推荐使用Executors创建线程池,推荐使用ThreadPoolExecutor创建线程池
Executors
提供的工厂方法虽然方便,但大多数存在 隐藏风险:
工厂方法 隐患 newFixedThreadPool
/newSingleThreadExecutor
使用 无界队列 ( LinkedBlockingQueue
) → 队列无限积压,容易 OOMnewCachedThreadPool
线程数几乎无限 → 可能创建大量线程导致 系统崩溃 newScheduledThreadPool
定时线程池虽然安全,但默认队列同样可能无限积压任务 使用样例
//1. 固定线程池 ExecutorService fixedPool = Executors.newFixedThreadPool(5); //2. 缓存线程池 ExecutorService cachedPool = Executors.newCachedThreadPool(); //3. 单线程线程池 ExecutorService singlePool = Executors.newSingleThreadExecutor(); //4. 定时线程池 ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2);
总结:方便但不安全,生产环境不推荐直接使用。
2. 推荐使用ThreadPoolExecutor
不推荐使用Executors创建线程池,推荐使用ThreadPoolExecutor创建线程池
这里详情可以去看:并发编程--线程池(2)ThreadPoolExecutor以及他的7个参数-CSDN博客
ThreadPoolExecutor 的优势
可自定义核心线程数和最大线程数 → 精准控制资源。
可选择有界队列 → 避免任务无限积压。
可设置拒绝策略 → 系统负载过高时安全处理任务。
可自定义线程工厂 → 便于线程命名、监控和调试。
性能可调优 → 根据系统实际情况调整参数。
使用样例
ThreadPoolExecutor pool = new ThreadPoolExecutor(10, // corePoolSize 核心线程数50, // maximumPoolSize 最大线程数60, TimeUnit.SECONDS, // keepAliveTime 空闲线程存活时间new ArrayBlockingQueue<>(100), // 有界队列Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 );
3. Executors 与 ThreadPoolExecutor 区别
特点 Executors 工厂方法 ThreadPoolExecutor 配置灵活性 低,封装好的线程池 高,可自定义线程数、队列、拒绝策略等 队列 newFixedThreadPool / newSingleThreadExecutor → 无界队列(可能 OOM) 可指定有界队列或无界队列 最大线程数 默认固定 可自定义 是否推荐 不推荐生产使用 推荐,适合生产环境 4. 三者关系图
Executor (接口) ↑ ExecutorService (接口)↑ AbstractExecutorService (抽象类)↑ ThreadPoolExecutor (核心实现类)↑ Executors (工具类封装)
三、Executors 常用工厂方法
方法 类型 特点 newFixedThreadPool(int n)
固定线程池 核心线程数 = 最大线程数 = n,使用 无界队列 newCachedThreadPool()
缓存线程池 核心线程数 = 0,最大线程数几乎无限,线程空闲会回收 newSingleThreadExecutor()
单线程线程池 只有一个线程顺序执行任务,使用 无界队列 newScheduledThreadPool(int n)
定时线程池 支持延迟和周期任务 ⚠️ 注意:
Executors 工厂方法方便,但多数使用 无界队列 或 无限线程,可能导致 OOM 或线程过多。
推荐直接使用 ThreadPoolExecutor 并指定合理参数,适合生产环境。
四、ThreadPoolExecutor 构造方法解析
public ThreadPoolExecutor(int corePoolSize, // 核心线程数int maximumPoolSize, // 最大线程数long keepAliveTime, // 非核心线程空闲存活时间TimeUnit unit, // 时间单位BlockingQueue<Runnable> workQueue, // 任务队列ThreadFactory threadFactory, // 线程工厂RejectedExecutionHandler handler // 拒绝策略 )
核心线程:始终保留,即使空闲也不销毁(除非 allowCoreThreadTimeOut=true)。
非核心线程:空闲超过 keepAliveTime 会被回收。
任务队列:
有界队列(ArrayBlockingQueue):可限制排队任务数,避免 OOM。
无界队列(LinkedBlockingQueue):任务无限积压,可能导致 OOM。
拒绝策略:
AbortPolicy
(默认):抛出异常。
CallerRunsPolicy
:调用者线程执行任务。
DiscardPolicy
:直接丢弃任务。
DiscardOldestPolicy
:丢弃队列中最旧任务,执行新任务。
五、线程池总结
概念:线程池是复用线程、控制线程数量、管理任务队列的机制。
Java 体系:
Executor:顶层接口,定义任务执行规范。
ExecutorService:扩展接口,支持任务管理和结果返回。
ThreadPoolExecutor:核心实现类,可高度自定义线程池参数。
Executors:工厂类,快速创建常用线程池(封装 ThreadPoolExecutor)。
使用建议:
生产环境尽量直接使用 ThreadPoolExecutor,指定合理参数(线程数、队列、拒绝策略)。
避免直接使用 Executors 的无界队列线程池。