ThreadPoolExecutor的RejectedExecutionHandler什么时候触发
java为我们提供的RejectedExecutionHandler的几种实现及避坑
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);
}
}
}
丢弃队列头部即入队时间最早的任务,
提交当前任务。这种在业务场景下不
会采取,否则造成业务故障。
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());
}
}
直接抛出异常,当前任务不会提交到线程池队列中。由我们业务方自己处理当前不能处理的任务。这是线程池默认使用的拒绝任务的策略。
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();
}
}
}
当前提交任务的线程执行任务。一般我们在把串行执行的业务逻辑拆分成并行,优化性能的时候使用(因为你也不知道线程池是否已满,退而求其次变成串行执行也无妨)。
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) {
}
}
什么也不处理策略。这种策略我们坚决不使用,而且使用
java.util.concurrent.AbstractExecutorService#submit(java.util.concurrent.Callable<T>)
【避坑】:提交任务,使用java.util.concurrent.Future#get()会一直阻塞(强制使用java.util.concurrent.Future#get(long, java.util.concurrent.TimeUnit))。
总结