一. 前言
1. 为什么要用线程池?
① 传统的多线程方式(继承Thread类 & 实现Runable接口)
- 每次新建线程 、销毁线程对象消耗资源,响应速度慢。
- 线程缺乏统一管理,容易出现阻塞情况。
② 线程池的优点
降低因线程的创建和销毁所带来的性能开销(通过重用缓存在线程池的线程)。
提高线程的响应速度和执行效率(重用线程达到不需要创建线程即可马上执行,线程管理可以优化线程的执行顺序)。
2. 核心参数
参数 | 意义 | 说明 |
---|---|---|
corePoolSize | 核心线程数 | 默认情况下,核心线程会一直存活,包括空闲状态 |
maximumPoolSize | 线程池所能容纳的最大线程数 | 当活动线程达到该数值后,后续的新任务将会阻塞 |
keepAliveTime | 非核心线程,闲置超时时长 | 超过该时长,非核心线程会被回收 |
unit | 指定keepAliveTime参数的时间单位 | 常用:(毫秒)TimeUnit.MILLISECONDS,(秒)TimeUnit.SECONDS,(分)TimeUnit.MINUTES |
workQueue | 任务队列 | 通过线程池的execute()方法提交的Runable对象将存储在该参数中 |
treadFactory | 线程工厂 | 作用:为线程池创建新线程 具体使用:Thread new Thread(Runable r) |
上述6个参数的配置 决定了 线程池的功能,具体设置时机:创建线程池类对象时传入。
1 | ThreadPoolExecutor类 = 线程池的真正实现类 |
1 | // 创建线程池对象如下 |
二. 使用流程
1 | // 1. 创建线程池 |
三. 常见的四类功能线程池
根据参数的不同配置,Java
中最常见的线程池有4类:
- 定长线程池(
FixedThreadPool
) - 定时线程池(
ScheduledThreadPool
) - 可缓存线程池(
CachedThreadPool
) - 单线程化线程池(
SingleThreadExecutor
)
1. 定长线程池(FixedThreadPool)
① 特点
只有核心线程 & 不会被回收、线程数量固定、任务队列无大小限制(超出的线程任务会在队列中等待)。
② 应用场景
控制线程最大并发数。
③ 具体使用
通过 Executors.newFixedThreadPool 创建。
④ 例子
1 | // 1. 创建定长线程池对象 & 设置线程池线程数量固定为3 |
2 定时线程池(ScheduledThreadPool )
① 特点
核心线程数量固定、非核心线程数量无限制(闲置时马上回收)。
② 应用场景
执行定时 / 周期性 任务。
③ 具体使用
通过 Executors.newScheduledThreadPool 创建。
④ 例子
1 | // 1. 创建 定时线程池对象 & 设置线程池线程数量固定为5 |
3 可缓存线程池(CachedThreadPool)
① 特点
只有非核心线程、线程数量不固定(可无限大)、灵活回收空闲线程(具备超时机制,全部回收时几乎不占系统资源)、新建线程(无线程可用时)。
任何线程任务到来都会立刻执行,不需要等待。
② 应用场景
执行大量、耗时少的线程任务。
③ 具体使用
通过 Executors.newCachedThreadPool 创建。
④ 例子
1 | // 1. 创建可缓存线程池对象 |
4 单线程化线程池(SingleThreadExecutor)
① 特点
只有一个核心线程(保证所有任务按照指定顺序在一个线程中执行,不需要处理线程同步的问题)。
② 应用场景
不适合并发但可能引起IO阻塞性及影响UI线程响应的操作,如数据库操作,文件操作等。
③ 具体使用
通过 Executors.newSingleThreadExecutor 创建。
④ 例子
1 | // 1. 创建单线程化线程池 |