文章目录
一、什么是线程池中的拒绝策略?
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
1、谈拒绝策略前,需要先说一下Java中的线程池ThreadPoolExecutor,对于Java中线程池的使用一般都是通过new ThreadPoolExecutor来创建,而通过其构造方法可以发现对于其创建需要7个参数:
在这里插入代码片
1. int corePoolSize -----------------------------------核心线程数
2. int maximumPoolSize---------------------------------最大线程数
3. long keepAliveTime----------------------------------时间大小
4. TimeUnit unit---------------------------------------时间类型
5. BlockingQueue<Runnable> workQueue-------------------任务队列
6. ThreadFactory threadFactory-------------------------创建线程的工厂
7. RejectedExecutionHandler handler--------------------拒绝策略
对于这个7个参数线程池是如何使用的呢,接着往下看,线程池的执行流程:
1、当向线程池提交任务时,会去创建核心线程
2、当任务太多,核心线程来不及处理时,会将任务先放入任务队列
3、当任务队列满了,会去创建新的线程处理任务,但不会超过最大线程数
4、当线程空闲超过我们设置的时间大小,则回去销毁(核心线程数-最大线程数)之间的线程
5、当队列已满,总线程数已达我们设置的最大线程数时,新的任务进来则会触发我们设置的拒绝策略
总结:也即是说在线程池队列已满,且已创建到最大线程数量时,新的任务提交至线程池,线程池无法处理新的任务,则会对新的任务线程进行丢弃,抛异常,优先处理,丢弃队列中最久等待任务,这些对新的任务线程的处理则称之为线程池的拒绝策略
二、拒绝策略有哪些
1、RejectedExecutionHandler(拒绝执行处理程序)
线程池中的拒绝策略都实现了RejectedExecutionHandler下rejectedExecution方法:
public interface RejectedExecutionHandler {
/**
* Method that may be invoked by a {@link ThreadPoolExecutor} when
* {@link ThreadPoolExecutor#execute execute} cannot accept a
* task. This may occur when no more threads or queue slots are
* available because their bounds would be exceeded, or upon
* shutdown of the Executor.
*
* <p>In the absence of other alternatives, the method may throw
* an unchecked {@link RejectedExecutionException}, which will be
* propagated to the caller of {@code execute}.
*
* @param r the runnable task requested to be executed
* @param executor the executor attempting to execute this task
* @throws RejectedExecutionException if there is no remedy
*/
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
丢弃策略(DiscardPolicy )
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
1、可以在方法rejectedExecution看到,没有任何的代码处理逻辑,也就是对新的任务不做任何处理,翻译过来就是丢弃策略,业务中慎用。
中止策略(AbortPolicy )
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
1、在代码中可见,在rejectedExecution方法中抛出了RejectedExecutionException异常,会对代码的运行进行中止。
优先处理策略(CallerRunsPolicy )
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
/**
* Executes task r in the caller's thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
1、对新的任务进行优先执行,直接调用其run方法
丢弃最老任务(DiscardOldestPolicy )
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
public DiscardOldestPolicy() { }
/**
* Obtains and ignores the next task that the executor
* would otherwise execute, if one is immediately available,
* and then retries execution of task r, unless the executor
* is shut down, in which case task r is instead discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
//丢弃队列中最老,最先进来的任务
e.getQueue().poll();
e.execute(r);
}
}
}
1、拿到队列,调用队列的poll方法对队列中最老的任务进行丢弃,再将新的任务放入队列中