线程池的七大参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
......
}
- corePoolSize:线程池中常驻的核心线程数
- maxiumPoolSize:能够容纳的最大线程数,必须大于等于1。
- keepAliveTime:多余空闲线程的存活时间。当前线程数量超过corePoolSize时,当空闲时间达到keepAliveTime时,多余线程会被销毁直到只剩下corePoolSize个线程位置。
- unit:keepAliveTime的单位
- workQueue:任务队列,被提交但未被执行的任务
- threadFactory:生成线程池中工作线程的线程工厂,用于创建线程,默认即可。
- handler:拒绝策略,表示当队列满了并且工作线程大于等于最大线程数时,如何拒绝请求。
线程池底层工作原理
1、在创建线程池后,等待提交过来的任务请求
2、当调用execute()方法添加一个请求任务时,线程池会做如下判断:
2.1、如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务;
2.2、如果正在运行的线程数大于或等于corePoolSize,那么将这个任务放入队列;
2.3、如果这个时候队列满了且正在运行的线程数量还小于maxmunPoolSize,那么还是要创建非核心线程立刻运行这个任务;
2.4、如果队列满了且正在运行的线程数量大于或等于maxmumPoolSize,那么线程池会启动饱和拒绝策略来执。
3、当一个线程完成任务时,它会从队列中取下一个任务来执行。
4、当一个线程无事可做超过一定时间(keepAliveTime)时,线程池会判断:
如果当前运行的线程数大于core Pool Size,那么这个线程就会被停掉,索所以线程池的所以任务完成后它最终会收缩到corePoolSize打大小。
线程池的四种拒绝策略
- AbortPolicy(默认):直接抛出RejectedException。
- CallerRunsPolicy:不会抛弃任务也不会抛出异常,而是回退给调用者
- DiscardOldestPolicy:丢弃等待最久的任务。
- DiscardPolicy:直接丢弃任务,不做任何处理。
如何合理配置线程池
-
CPU密集型:CPU核数+1个线程的线程池
-
IO密集型
- IO密集型任务线程不是一直在执行任务,则应配置尽可能多的线程:CPU核数*2
- 大部分线程都阻塞,故需要多配置线程数:CPU核数/(1-阻塞系数),阻塞系数在0.8-0.9之间