线程池知识点总结
线程池是一种线程管理机制,通过预先创建一定数量的线程并复用它们,避免频繁创建和销毁线程带来的资源开销,是并发编程中的核心组件。以下从核心概念、工作机制、关键参数等方面进行总结:
一、线程池的核心作用
- 降低资源消耗:线程复用减少线程创建(涉及内核态操作)和销毁的开销。
- 控制并发强度:避免无限制创建线程导致的CPU切换过载、内存耗尽等问题。
- 提高响应速度:预先创建的线程可直接处理任务,无需等待线程初始化。
- 统一管理任务:支持任务排队、拒绝策略、监控等功能,便于任务生命周期管控。
二、核心参数(以Java ThreadPoolExecutor
为例)
线程池的行为由7个核心参数决定,需根据任务特性(如CPU密集/IO密集)合理配置:
参数 | 作用描述 |
| 核心线程数:线程池长期保留的线程数量(即使空闲也不销毁,除非设置 |
| 最大线程数:线程池允许创建的最大线程数(核心线程+临时线程)。 |
| 临时线程存活时间:当线程数超过 |
|
|
| 任务队列:用于存放未被立即执行的任务(当核心线程都在工作时)。 |
| 线程工厂:用于创建线程(可自定义线程名称、优先级等)。 |
| 拒绝策略:当任务队列满且线程数达 |
三、工作流程(任务提交后)
- 若当前线程数 <
corePoolSize
:直接创建核心线程执行任务。 - 若当前线程数 ≥
corePoolSize
:将任务加入workQueue
等待。 - 若
workQueue
已满,且当前线程数 <maximumPoolSize
:创建临时线程执行任务。 - 若
workQueue
已满,且当前线程数 ≥maximumPoolSize
:触发handler
拒绝策略
四、拒绝策略(Java默认4种)
当任务无法被处理时(队列满+线程达上限),需通过拒绝策略处理,避免任务丢失或系统崩溃:
策略类 | 行为描述 |
| 抛出 |
| 让提交任务的线程(如main线程)自己执行任务(降低提交速度,缓解压力)。 |
| 直接丢弃新任务(无提示,可能丢失任务)。 |
| 丢弃任务队列中最旧的任务(队头),再尝试提交新任务。 |
注:可自定义拒绝策略(实现RejectedExecutionHandler
接口),如记录日志、持久化任务等。
五、常见线程池类型(Java Executors
提供)
Executors
封装了几种常用线程池,但不推荐生产环境使用(存在资源风险):
线程池类型 | 核心参数配置 | 风险点 |
| 核心线程数=最大线程数,队列 | 队列无界可能导致OOM(任务堆积过多)。 |
| 核心线程数=0,最大线程数=Integer.MAX_VALUE,队列 | 最大线程数过大,可能创建大量线程导致OOM。 |
| 核心线程数=最大线程数=1,队列 | 同 |
| 核心线程数固定,最大线程数=Integer.MAX_VALUE,支持定时/周期性任务。 | 最大线程数过大,可能创建大量线程导致OOM。 |
package com.day5;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;public class Demo06 {public static void main(String[] args) {
// int i = Runtime.getRuntime().availableProcessors();
// System.out.println(i);//1.固定大小线程池ExecutorService fixedThreadPool= Executors.newFixedThreadPool(5);//2.单线程线程池ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();//3.缓存线程池ExecutorService cachedThreadPool = Executors.newCachedThreadPool();//适合那种大型数量的任务,快速的去创建线程//4.定时任务线程池ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);//提交任务fixedThreadPool.execute(()-> System.out.println("Task exexcuted"));//关闭线程池fixedThreadPool.shutdown();}
}
六、线程池状态(生命周期)
ThreadPoolExecutor
通过状态控制线程池行为,状态流转不可逆:
状态 | 描述 | 触发方式 |
| 运行中:接受新任务,处理队列任务。 | 线程池初始化后默认状态。 |
| 关闭中:不接受新任务,但处理队列剩余任务。 | 调用 |
| 停止中:不接受新任务,不处理队列任务,中断所有正在执行的任务。 | 调用 |
| 整理中:所有任务终止,工作线程数=0,准备执行 |
|
| 终止: |
|
七、使用注意事项
- 避免使用
Executors工具类
:默认线程池的队列或最大线程数可能导致OOM,推荐手动创建ThreadPoolExecutor
并指定参数。 - 合理配置核心参数:
- CPU密集型任务(如计算):核心线程数 ≈ CPU核心数(减少切换开销)。
- IO密集型任务(如网络/磁盘操作):核心线程数 ≈ CPU核心数 * 2(利用线程空闲时间)。
- 任务队列选择:
- bounded队列(如
ArrayBlockingQueue
):控制任务堆积上限,避免OOM。 - 避免无界队列(如
LinkedBlockingQueue
)除非明确任务量可控。
- bounded队列(如
- 优雅关闭线程池:通过
shutdown()
(平缓关闭)或shutdownNow()
(强制关闭),并配合awaitTermination()
等待终止。 - 监控线程池:通过
getActiveCount()
(活跃线程数)、getQueue().size()
(队列任务数)等方法监控状态,及时调整参数。