什么时候使用线程池?
- 单个任务处理时间比较短
- 需要处理的任务数量很大
线程池优势
- 重用存在的线程,减少线程创建,消亡的开销,提高性能
- 提高响应速度,当任务到达时,任务可以不需要的等到线程创建就能立即执行。
- 提高线程的可管理性,可统分配, 调优和监控。
线程池参数
线程池的执行流程
1、如果线程池中的线程数量少于corePoolSize,就创建新的线程来执行新添加的任务
2、如果线程池中的线程数量大于等于corePoolSize,但队列workQueue未满,则将新添加的任务放到workQueue中
3、如果线程池中的线程数量大于等于corePoolSize,且队列workQueue已满,但线程池中的线程数量小于maximumPoolSize,则会创建新的线程来处理被添加的任务
4、如果线程池中的线程数量等于了maximumPoolSize,就用RejectedExecutionHandler来执行拒绝策略
拒绝策略
- 直接抛出异常
- 使用调用者的线程来处理
- 直接丢掉这个任务
- 丢掉最老的任务
运行状态 - 线程池一共有五种运行状态:
-
RUNNING
- 运行状态。接受新任务,并且也能处理阻塞队列中的任务。 -
SHUTDOWN
-关闭状态。不接受新任务,但可以处理阻塞队列中的任务。- 在线程池处于
RUNNING
状态时,调用shutdown
方法会使线程池进入到该状态。 finalize
方法在执行过程中也会调用shutdown
方法进入该状态。
- 在线程池处于
-
STOP
- 停止状态。不接受新任务,也不处理队列中的任务。会中断正在处理任务的线程。在线程池处于RUNNING
或SHUTDOWN
状态时,调用shutdownNow
方法会使线程池进入到该状态。 -
TIDYING
- 整理状态。如果所有的任务都已终止了,workerCount
(有效线程数) 为 0,线程池进入该状态后会调用terminated
方法进入TERMINATED
状态。 -
TERMINATED
- 已终止状态。在terminated
方法执行完后进入该状态。默认terminated
方法中什么也没有做。进入
TERMINATED
的条件如下:- 线程池不是
RUNNING
状态; - 线程池状态不是
TIDYING
状态或TERMINATED
状态; - 如果线程池状态是
SHUTDOWN
并且workerQueue
为空; workerCount
为 0;- 设置
TIDYING
状态成功。
- 线程池不是
常用的三个阻塞队列
1、ArrayBlockingQueue
是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。
2、LinkedBlockingQueue
一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列
3、SynchronousQueue
一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool(5)使用了这个队列。