ThreadPoolExecutor的执行流程和拒绝策略
一、执行流程
ThreadPoolExecutor是Java标准库的线程池,Executors本质上是对其进行封装后的类。
先来认识一下ThreadPoolExecutor的构造方法:
ThreadPoolExecutor的构造方法 |
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) |
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory) |
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler) |
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory, RejectedExecutionHandler) |
我们主要看一下最后一个构造方法,这个方法的参数是最为齐全的~
参数一:int corePoolSize
表示线程池的核心线程数量,核心线程即使处于空闲状态也不会被销毁。
参数二:int maximumPoolSize
表示线程池的最大线程数量,最大线程数量 = 核心线程数 + 临时线程数;临时线程处于空闲状态达到一定时间,就会被销毁。
参数三:long keepAliveTime
表示临时线程可以处于空闲状态的最长时间。
参数四:TimeUnit unit
表示参数三的时间单位 ,可以设置为纳秒、微秒、毫秒、秒、分钟等单位。
参数五:BlockingQueue<Runnable> workQueue
给线程池传入一个工作队列。
参数六:ThreadFactory
ThreadFactory是一个接口,描述了线程的创建方式,我们可以通过ThreadFactory对象手动来指定如何创建线程。
参数七:RejectedExecutionHandler
表示线程池的拒绝策略,下面会详细说~
示例:创建一个核心线程数为5,最大线程数为10,任务队列容量为100的线程池
认识了构造方法,我们才能理解它的执行流程~
ThreadPoolExecutor的执行流程是这样的:
1、当线程池中新加入一个任务时,先判断核心线程数是否达到最大值,如果为false则创建一个核心线程执行任务,如果为true执行第二步;
2、判断当前任务队列是否已满,如果为false,则将任务加入到队列中等待执行;如果为true,则判断当前线程数是否达到最大线程数;
3、如果当前线程数没有达到最大线程数,则创建临时线程来执行任务,如果达到最大线程数,则执行拒绝策略。
二、拒绝策略
从上图可以看出,拒绝策略指的是线程池中线程数量达到最大值,任务队列为满时,来了新任务的处理方式。
标准库中提供了以下几种拒绝策略:
1、ThreadPoolExecutor.AbortPolicy
抛出一个RejectedExecutionException异常来拒绝执行任务:
2、ThreadPoolExecutor.CallerRunsPolicy
新加入的任务由线程池的调用线程来执行;
如果调用线程被销毁了,那么新加入的任务就会被丢弃。
3、ThreadPoolExecutor.DiscardOdestPolicy
丢弃当前还未被执行的任务中的第一个任务,然后重新执行新加入的任务;如果线程池的调用线程被销毁了,那么新加入的任务就会被丢弃。
4、ThreadPoolExecutor.DiscardPolicy
直接丢弃新加入的任务。