一、线程池的执行流程总结
- 提交线程任务;
- 如果线程池中存在空闲线程,则分配一个空闲线程给任务,执行线程任务;
- 线程池中不存在空闲线程,则线程池会判断当前线程数是否超过核心线程数(corePoolSize)
- 若未超出核心线程数,则创建一个核心线程用来执行线程任务;
- 若超出核心线程数,则线程池会检查工作队列(workQueue)是否已满
- 如果工作队列未满,则将该线程任务存入工作队列中,当线程池中出现空闲线程,从工作队列中依次取出线程任务并执行;
- 如果工作队列已满,则判断是否超出最大线程数(maximumPoolSize)
- 若当前线程池中的线程数超出最大线程数,则执行拒绝策略(defaultHandler)。
- 若当前线程池中的线程数未超出最大线程数,则创建非核心线程数来执行线程任务。
二、线程池的配置参数总结
1.核心线程数:corePoolSize
int corePoolSize
核心线程数也就是线程池的最小线程数量。
- 核心线程会一直存活,不会被回收,除非设置了核心线程超时时间;
- 在创建线程池后,默认情况下,线程池中没有任何线程,调用
excute()
方法添加一个任务。
当线程池中没有空闲线程时,查看是否超过核心线程数:
- 线程数量小于核心线程数,则马上创建新的核心线程来执行线程任务。
- 线程数量大于核心线程数,则查看工作队列是否超出。
2.最大线程数:maximumPoolSize
int maximumPoolSize
是指线程池中允许的最大线程数量。
当工作队列已满,且存活线程数超过了核心线程数时,线程池判断“存活线程数”是否超过最大线程数:
- 未超过最大线程数:创建新线程来执行该任务。
- 超过最大线程数:执行拒绝策略。
3.非核心的空闲线程的存活时间:keepAliveTime
long keepAliveTime
当线程数大于核心线程数时,空闲的线程等待新任务到达的最大时间,如果超过这个时间线程还没有需要执行的任务,该空闲线程就会销毁。
4.keepAliveTime的单位:unit
TimeUnit unit
keepAliveTime的单位,枚举类型的TimeUnit类。
5.阻塞工作队列:workQueue
BlockingQueue<Runnable> workQueue
在任务执行之前,用来存储任务的工作队列,此队列只保存由excute()
方法提交的Runnable
类型的任务。
当存活的线程数大于核心线程数,查看工作队列:
- 工作队列未满:将新的请求任务加入工作队列;
- 工作队列已满:线程池判断是否超过最大线程数。
5.1 ArrayBlockingQueue
基于数组有界阻塞队列,FIFO(先进先出)。
- capacity:队列初始化大小
- fair:表示该队列中的可重入锁是否公平,默认为false
当线程池中已经存在最大数量的线程时候,再请求新的任务,这时就会将任务加入工作队列的队尾,一旦有空闲线程,就会取出队头执行任务。
5.2 LinkedBlockingQueue
基于链表的误解阻塞队列,默认最大容量为Integer.MAX_VALUE,可认为是无限队列,FIFO(先进先出)。
指定工作队列大小,则最大线程数量的限制是有效的。
5.3 SynchronousQueue
可以将SynchronousQueue
看作是一个没有容量的阻塞队列,它严格遵循FIFO(先进先出)的原则,但特殊的是,它不会保存任何元素,而是直接在不同的线程间进行传递。
6.线程工厂:threadFactory
ThreadFactory threadFactory
用于创建一个新线程时使用的工厂,可以用来设置线程名。
没有特别声明时,使用Executors工具类提供的默认线程工Executors.defaultThreadFactory()
。
自定义线程工厂时,要实现ThreadFactory接口,重写newThread()
方法。
7.拒绝策略:handler
RejectedExecutionHandler handler
当线程池内的线程被耗尽,并且工作队列已满,对于新提交的任务,将使用拒绝策略进行处理。
7.1 AbortPolicy:丢弃线程任务,并抛出异常
没有特别声明时,使用默认的拒绝策略defaultHandler
7.2 DiscardOldestPolicy:将工作队列的对头移除,线程池重新执行该线程任务
7.3 DiscardPolicy:直接丢弃该任务
7.4 CallerRunPolicy:线程池没有关闭时,线程自己调用run方法
7.5 自定义的拒绝策略:实现RejectedExecutionHandler接口
重写void rejectedExecution(Runnable r, ThreadPoolExecutor executor)
方法