文章目录
一、ThreadPoolExecutor介绍
1. 为什么要用线程池?
过于频繁的创建/销毁线程,会影响处理效率和运行速度,消耗系统资源,降低系统稳定性,一不小心搞崩公司系统直接下岗,而使用线程池可以避免这些问题,稳住饭碗,并且可以对线程这个稀缺资源进行管理、调优与监控
ThreadPoolExecutor的构造函数
2. ThreadPoolExecutor构造函数的核心参数
corePoolSzie: 线程核心池所能容纳的线程数,满后仍有任务进入则进入阻塞队列等待
maximumPoolSize: 线程池最多所能容纳的线程数,阻塞队列也满后,仍有任务进入,会新建线程(非核心线程)来执行任务,核心池线程数+新建线程数不得超过此参数数值,否则会触发拒绝策略拒绝任务。即新建的非核心线程数最大值 = maximumPoolSize - corePoolSize
keepAliveTime: 非核心线程若超过此参数指定时间没有任务执行,则销毁线程
TimeUnit unit: 上个参数的时间单位,TimeUnit是枚举类型,有七种参数:
NANOSECONDS : 1微毫秒 = 1秒 / 1000 * 1000 * 1000
MICROSECONDS : 1微秒 = 1秒 / 1000 * 1000
MILLISECONDS : 1毫秒 = 1秒 /1000
SECONDS : 秒
MINUTES : 分
HOURS : 小时
DAYS : 天
BlockingQueue<Runnable> workQueue: 阻塞队列,常用workQueue类型:
SynchronousQueue:这个队列接收到任务的时候,会直接提交给线程处理,而不保留它,如果所有线程都在工作怎么办?那就新建一个线程来处理这个任务!所以为了保证不出现<线程数达到了maximumPoolSize而不能新建线程>的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大
LinkedBlockingQueue:这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize
ArrayBlockingQueue:可以限定队列的长度,接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误
DelayQueue:队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务
threadFactory:用于创建工作线程的工厂。
handler:拒绝策略,往线程池添加任务时,将在下面两种情况触发拒绝策略:1)线程池运行状态不是 RUNNING;2)线程池已经达到最大线程数,并且阻塞队列已满时。
3. 线程池运行流程
4. 创建线程池实例
代码如下:
//创建核心线程池; 核心池容量=3; 最大线程数=10; 阻塞队列类型为ArrayBlockingQueue,容量=5; KeepAliveTime = 10ms
ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 10, 10L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5));
二、如何使用线程池
1.创建线程
代码如下:
public class MyThread implements Runnable{
//region 构造器
/**
* @param flag 线程编号
* @param currentBlockingQueueSize 当前阻塞队列等待的线程数量
*/
public MyThread(int flag, int currentBlockingQueueSize) {
this.flag = flag;
this.currentBlockingQueueSize = currentBlockingQueueSize;
}
//endregion
//region 变量
private int flag;
private int currentBlockingQueueSize;
//endregion
//region run函数重写
@Override
//线程运行
public void run() {
System.out