线程池
- 线程池
- 线程池接口
- 线程池参数
- 线程池分类
- 动态数目线程池
- 固定数目线程池
- 单例线程池
- 任务调度线程池
- 线程池的执行流程
线程池
线程池接口
线程池参数
1、corePoolSize:核心线程数,线程池中最少线程,核心线程不会被回收。
2、maximumPoolSize:最大线程数,线程池中最多线程,包含核心线程数,不能小于核心线程数。
3、keepAliveTime:非核心线程(除去核心线程之外的线程)存活时间,如果非核心线程的空闲时间大于此参数,将会被回收。
4、TimeUnit:时间单位,参数keepAliveTime的时间单位。
5、BlockingQueue:阻塞工作队列,当来一个新的线程任务时,如果当前没有空闲线程,此线程任务将会进入阻塞工作队列中进行等待。
6、ThreadFactory:线程工厂,用于创建线程,自定义线程的名称。(需要实现ThreadFactory接口,实现newThread()方法,在此方法中,新建Thread对象,通过调用setName()方法给线程定义名称。)
7、RejectedExecutionHandler:拒绝策略,当线程池中没有空闲线程,且阻塞工作队列已满,且最大线程数也已超出,此时再来线程任务将执行拒绝策略。
线程池分类
根据设定的参数不同分为下面四种常用的线程池:
动态数目线程池
Executors.newCachedThreadPool();
固定数目线程池
Executors.newFixedThreadPool(20);
单例线程池
Executors.newSingleThreadExecutor();
任务调度线程池
Executors.newScheduledThreadPool(20);
线程池的执行流程
首先,通过execute()或者submit()提交线程任务到线程池中,然后由线程池判断是否可以执行,反之执行拒绝策略。
如上图所示,就是线程池的执行过程,可以分为五个主要步骤:
1.提交任务后会首先进行判断是否存在空闲线程,如果存在直接执行线程任务。
2.若果当前工作线程数与核心线程数的比较,如果当前工作线程数小于核心线程数,则直接调用 addWorker() 方法创建一个核心线程去执行任务;
3.如果工作线程数大于核心线程数,即线程池核心线程数已满,则新任务会被添加到阻塞队列中等待执行,当然,添加队列之前也会进行队列是否为空的判断;
4.如果线程池里面存活的线程数已经等于核心线程数了,且阻塞队列已经满了,再会去判断当前线程数是否已经达到最大线程数 maximumPoolSize,如果没有达到,则会调用 addWorker() 方法创建一个非核心线程去执行任务;
5.如果当前线程的数量已经达到了最大线程数时,当有新的任务提交过来时,会执行拒绝策略
总结来说就是优先核心线程、阻塞队列次之,最后非核心线程。