系列文章目录
关于线程池的文章可以看这里
前言
提示:可以先看上述文章中对线程池的描述:
线程池拒绝策略:卷起来,我就要强制给他分各类:
1、抛出不抛出异常:
拒绝策略会通知调用者任务无法被线程池处理。
示例:AbortPolicy
2、运行不运行任务:
拒绝策略允许调用者线程自己执行被拒绝的任务。
示例:CallerRunsPolicy
3、丢弃不丢弃任务:
拒绝策略静默地丢弃无法处理的任务,不执行也不抛出异常。
提示:以下是本篇文章正文内容,下面案例可供参考
一、四种拒绝策略使用场景
java中的ThreadPoolExecutor提供了四种拒绝策略(RejectedExecutionHandler),当任务无法提交给线程池执行。
(例如,当工作队列已满且线程数量已达到最大线程数时)时,这些策略定义了如何处理这些额外的任务。以下是四种预定义的拒绝策略及其用途和使用场景:
1、AbortPolicy:
这是默认的拒绝策略。当任务被拒绝时,策略会抛出RejectedExecutionException异常。
作用:通知调用者任务无法被线程池处理。
使用场景:当你想要确保所有任务在提交时都得到处理,如果线程池无法处理,则通知应用程序并允许它响应拒绝,如记录日志、触发报警等。
2、CallerRunsPolicy:
此策略不会丢弃任务,也不会抛出异常,而是由提交任务的线程自身来运行这个任务。
作用:调用者线程自己执行任务,减缓新任务的提交速度。
使用场景:在不想丢弃任务并且可以接受调用者执行任务的延迟时使用。这样可以降低新任务的提交速度,有助于"平滑"过载的任务进入线程池。
3、DiscardPolicy:
此策略默默地丢弃被拒绝的任务,不抛出任何异常。
作用:简单地放弃无法处理的任务,没有任何通知或其他处理。
使用场景:适用于任务丢失对程序影响较小的环境,且希望系统在负载较重的情况下不记录额外的错误。
4、DiscardOldestPolicy:
此策略将丢弃最旧的未处理任务(即工作队列中的队头元素),并尝试重新提交新任务。
作用:放弃在队列中等待时间最长的任务,以便为新提交的任务腾出空间。
使用场景:当你想要牺牲一些老的待执行任务来处理新提交的任务时使用。适合任务执行速度比产生速度快,同时任务时效性强的场景。
总结:
在选择使用哪种拒绝策略时,你应该考虑到应用程序的具体需求和行为。例如,可以基于任务的重要程度和接受程度,系统的容错性,以及任务丢失对系统可能产生的后果。
自定义拒绝策略:
除了上述提供的策略之外,你还可以通过实现RejectedExecutionHandler接口来创建自定义的拒绝策略,从而根据特定的需求执行自定义的处理逻辑。
二、代码case
public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 在这里实现你自己的拒绝逻辑,比如记录日志、做一些清理工作等
System.out.println("任务被拒绝执行: " + r.toString());
}
}
// 然后在创建线程池时使用你的拒绝策略
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
workQueue,
Executors.defaultThreadFactory(),
new MyRejectedExecutionHandler()
);
总结
学习道路任重道远,没事多敲一敲代码,再就是多理解业务背后的价值
代码:一个工具而已啦