线程池ThreadPoolExecutor拒绝策略RejectedExecutionHandler
  TEZNKK3IfmPf 2023年11月15日 50 0

问题1:什么时候触发拒绝策略?

问题2:拒绝策略有哪些?

问题3:默认的拒绝策略是什么?

问题4:你实际开发经历中的拒绝策略是什么?

创建线程池

核心线程数、最大线程数、空闲存活时间根据业务决定

任务队列避免使用无界队列,以免产生OOM

int coreSize = 4;
int maximumPoolSize = 8;
long keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(20);
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

ThreadPoolExecutor pool = new ThreadPoolExecutor(coreSize,maximumPoolSize,keepAliveTime,unit,workQueue,handler);

拒绝策略有哪些

严格来说,只要实现了RejectedExecutionHandler接口的,都可以作为拒绝策略,这里讨论的是JUC自带的拒绝策略。

上源码……

package java.util.concurrent;

/**
* A handler for tasks that cannot be executed by a {@link ThreadPoolExecutor}.
*
* @since 1.5
* @author Doug Lea
*/
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);
}

上源码显示,JUC自带的拒绝策略有四个

AbortPolicy

抛出异常RejectedExecutionException

/**
* A handler for rejected tasks that throws a
* {@code RejectedExecutionException}.
*/
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());
}
}


AbortPolicy是JUC的默认拒绝策略

/**
* The default rejected execution handler
*/
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();

CallerRunsPolicy

如果线程池还没关闭,就在主线程中执行这个任务,否则任务将被丢弃

/**
* A handler for rejected tasks that runs the rejected task
* directly in the calling thread of the {@code execute} method,
* unless the executor has been shut down, in which case the task
* is discarded.
*/
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();
}
}
}

DiscardOldestPolicy

喜新厌旧,将任务队列中最久未处理(oldest unhandled)的任务丢弃,然后尝试执行当前任务,如果线程池关闭了,这个任务也将被丢弃

/**
* A handler for rejected tasks that discards the oldest unhandled
* request and then retries {@code execute}, unless the executor
* is shut down, in which case the task is discarded.
*/
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);
}
}
}

DiscardPilicy

佛系拒绝,什么也不做

/**
* A handler for rejected tasks that silently discards the
* rejected task.
*/
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) {
}
}

揭晓答案

什么时候触发拒绝策略?

一图胜千言

线程池ThreadPoolExecutor拒绝策略RejectedExecutionHandler

拒绝策略有哪些?

线程池ThreadPoolExecutor拒绝策略RejectedExecutionHandler

 

默认的拒绝策略是什么?

线程池ThreadPoolExecutor拒绝策略RejectedExecutionHandler

 

你实际开发经历中的拒绝策略是什么?

分场景:看实际场景中任务重要性,如果是不重要的任务,默认的拒绝策略就好了,佛系,无为而治,什么也不做

如果任务很重要,不能丢,看了上面的四种拒绝策略,业务不允许丢弃任务的场景里,都不靠谱,就需要重写RejectedExecutionHandler接口自定义拒绝策略

比如当发生拒绝时将任务转发到MQ中,稍后再处理

另外多提一句,这里就是23中设计模式中——策略模式,使用的是一个典型场景,面试八股文奇怪的知识又增加了!

 


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月15日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   22天前   49   0   0 java
  TEZNKK3IfmPf   2024年05月31日   55   0   0 java
TEZNKK3IfmPf