使用线程池解决了我们手动去创建线程的过程,同时也可以实现线程的复用;大大节省更多资源和时间。
我们可以定制不同的线程池,方便为以后提交任务使用。往往有时候我们设置的线程数量满足不了使用场景时,线程池就会通过一些策略处理超出的任务。下面我们看看线程池是如何解决任务超出。
线程池的拒绝策略父接口
// 拒绝执行处理程序
public interface RejectedExecutionHandler {
// 当提交的任务超出了线程池的处理范围时,,可能由ThreadPoolExecutor调用的方法。
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
AbortPolicy(默认策略)
// 抛出异常RejectedExecutionException
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
// 抛出异常
// xx的任务被xx线程池拒绝
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
DiscardPolicy
// 它默默地丢弃被拒绝的任务。
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
// 什么都不做,具有丢弃任务 r 的效果
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
DiscardOldestPolicy
// 丢弃最旧的未处理请求,然后重试execute ,除非执行程序被关闭,在这种情况下任务被丢弃。
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
public DiscardOldestPolicy() { }
// 获取并忽略 executor 将执行的下一个任务,如果一个任务立即可用,然后重试任务 r 的 执行,除非 executor 被关闭,在这种情况下任务 r 被丢弃
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 检查线程池是否关闭,
// 没有关闭则进入方法
// 关闭则将任务丢弃
if (!e.isShutdown()) {
// 将阻塞队列在最后一个任务移除
e.getQueue().poll();
// 将新的任务提交放入队列中
e.execute(r);
}
}
}
CallerRunsPolicy
// 直接在execute方法的调用线程中运行被拒绝的任务,除非执行程序已关闭,在这种情况下,任务将被丢弃。
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
// 在调用者的线程中执行任务 r,除非执行者已经关闭,在这种情况下任务被丢弃。
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 检查线程池是否关闭
// 没有关闭则进入方法
// 反之丢弃任务
if (!e.isShutdown()) {
// 调用run方法执行任务
// 在调用者线程中执行此任务
r.run();
}
}
}