目录
一.什么是线程池的拒绝策略:
要知道什么是拒绝策略我们先要弄清楚线程池创建时的七个参数都是什么:
int corePoolSize, //核心线程数量
int maximumPoolSize, //最大线程数量
long keepAliveTime, //线程回收时间
TimeUnit unit, //回收时间单位
BlockingQueue<Runnable> workQueue, //工作队列,负责存在任务
ThreadFactory threadFactory, //线程工厂 ,负责创建线程
RejectedExecutionHandler handler) //拒绝策略
下图为线程池创建的源码:
线程池的启动过程:
1.每过来一个任务会启动一个线程去执行
2.当核心线程数用完后,会把新来的任务存入阻塞队列中
3.阻塞队列存满后,会再启动超过核心线程数量到最大线程数量之间的线程
4.当线程的数量达到最大线程数量,再来任务就启动拒绝策略
总结:线程池的工作队列已满,且线程数量以达到最大线程数量时,这时再给线程池添加新的任务时,对任务的处理过程就是拒绝策略
二.线程池拒绝策略的种类
线程池中的拒绝策略都实现了RejectedExecutionHandler接口并且重写rejectedExecution方法:
(一).线程池的默认的拒绝策略 AbortPolicy
如果我们创建线程池时不写拒绝策略,则使用默认的拒绝策略
这个拒绝策略就是直接丢弃当前被拒绝的任务,并抛出RejectedExecutionException异常(这是一个运行期异常)
(二).DiscardPolicy
这个拒绝策略就是丢弃当前被拒绝的任务,不抛出异常
(三).DiscardOldestPolicy
这个拒绝策略就是将最先进入工作队列等待的任务丢弃,然后接受新的任务
(四).CallerRunsPolicy
这个拒绝策略就是谁调用了本线程池,则谁来执行该任务,保证的任务不会丢失。
这里源码可以看出被拒绝的任务 r直接被调用了run()方法。没有创建新的线程去start()
三.自定义拒绝策略
上面四种拒绝策略时 Jdk提供给我们的,有时候我们不希望丢弃任务,那么前面三种拒绝策略都不能满足我们的需求,而最后一种CallerRunsPolicy拒绝策略当我们调用线程池的是主线程时,这种拒绝策略会将任务交给主线程来执行,这样如果任务量较大时,可能会阻塞主线程,所以这时需要我们自己定义一个拒绝策略来解决问题。
首先要自定义拒绝策略需要实现RejectedExecutionHandler接口并且重写rejectedExecution方法
这个时我使用AbortPolicy拒绝策略创建了一个核心线程数为1,最大线程处为1的线程,并且给它添加了5个任务,很显然最后多的三个任务被拒绝且抛弃了,
自定义一个拒绝策略