# Java 线程池的拒绝策略
当线程池无法处理新提交的任务时,Java提供了四种默认的拒绝策略(RejectedExecutionHandler
),可以根据应用场景选择合适的策略来处理此类情况。线程池在以下两种情况下会触发拒绝策略:
- 任务队列已满。
- 线程池中的线程数量已经达到了
maximumPoolSize
,无法再创建新的线程处理任务。
# 1. 四种默认拒绝策略
# 1.1 AbortPolicy
(默认策略)
- 作用:直接抛出
RejectedExecutionException
异常,拒绝处理新任务。 - 适用场景:当任务的执行是不可或缺的,并且程序希望立即发现任务被拒绝的情况时使用。
RejectedExecutionHandler abortPolicy = new ThreadPoolExecutor.AbortPolicy();
1
# 1.2 CallerRunsPolicy
- 作用:当线程池无法处理新任务时,由提交任务的线程(调用者线程)来执行该任务。这种策略既不会抛弃任务,也不会抛出异常。
- 适用场景:适用于任务量偶尔超出线程池负荷的场景,能降低任务丢失的风险,但可能会降低提交任务的线程处理其他任务的能力。
RejectedExecutionHandler callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();
1
# 1.3 DiscardPolicy
- 作用:默默丢弃无法处理的任务,不抛出任何异常。
- 适用场景:适用于对任务的丢弃不敏感,或允许在高负载情况下自动抛弃新任务的场景。
RejectedExecutionHandler discardPolicy = new ThreadPoolExecutor.DiscardPolicy();
1
# 1.4 DiscardOldestPolicy
- 作用:丢弃任务队列中等待时间最长的任务,然后尝试将新任务加入队列。
- 适用场景:适合对最新任务优先级较高的场景。通过丢弃较老的任务来腾出空间处理新任务。
RejectedExecutionHandler discardOldestPolicy = new ThreadPoolExecutor.DiscardOldestPolicy();
1
# 2. 自定义拒绝策略
除了上述四种默认策略,Java允许开发者通过实现RejectedExecutionHandler
接口来自定义拒绝策略,以应对更复杂的业务场景。
# 2.1 自定义拒绝策略示例
下面是一个自定义拒绝策略的例子,当任务被拒绝时,记录日志并重新尝试提交任务。
public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 记录被拒绝的任务
System.out.println("Task " + r.toString() + " rejected from " + executor.toString());
// 重新提交任务或执行其他处理
// 可以根据业务需求决定是否重新执行任务
}
}
// 在创建线程池时指定自定义拒绝策略
ExecutorService executorService = new ThreadPoolExecutor(
2, 4, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10),
new CustomRejectedExecutionHandler()
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 3. 选择拒绝策略的注意事项
- 系统稳定性:
AbortPolicy
会直接抛出异常,适合对系统稳定性要求较高的场景;而DiscardPolicy
和DiscardOldestPolicy
可能导致任务丢失,适合对稳定性要求不高的场景。 - 任务优先级:
DiscardOldestPolicy
适用于对最新任务优先级较高的场景,而CallerRunsPolicy
可以确保任务不会丢失,但可能会降低调用者线程的效率。 - 性能与资源:对于高并发和大负载场景,需要选择适当的拒绝策略以防止系统过载,同时根据业务逻辑决定任务是否可以丢弃或延迟执行。
# 4. 总结
Java线程池提供了四种默认的拒绝策略,分别是:
- AbortPolicy:抛出异常。
- CallerRunsPolicy:提交任务的线程自己执行任务。
- DiscardPolicy:丢弃无法执行的任务。
- DiscardOldestPolicy:丢弃最老的任务。
根据具体业务需求和系统资源限制,合理选择和配置拒绝策略,以确保系统在高并发场景下的稳定性和任务的高效处理。