线程池的拒绝策略有哪些?
在 Java 中,线程池的拒绝策略(RejectedExecutionHandler)用于处理当线程池无法接受新任务的情况(例如:线程池已关闭,或线程池、任务队列均达到容量上限)。Java 线程池(ThreadPoolExecutor
)提供了以下四种内置拒绝策略:
AbortPolicy(默认策略)
- 行为:直接抛出
RejectedExecutionException
异常,拒绝新任务。 - 适用场景:需要严格保证任务不被丢失的场景,开发者可以显式捕获异常并处理。
CallerRunsPolicy
- 行为:由提交任务的线程(调用者线程)直接执行该任务,而非交给线程池。
- 适用场景:希望降低任务提交速度,避免主线程提交任务过快导致系统过载(例如实现“负反馈”机制)。
DiscardPolicy
- 行为:直接静默丢弃新任务,不抛出异常也不执行任务。
- 适用场景:允许任务丢失的场景(如日志清理、不关键的后台任务)。
DiscardOldestPolicy
- 行为:丢弃任务队列中最旧的未处理任务(即队列头部的任务),然后尝试重新提交当前任务。
- 适用场景:允许丢弃旧任务以优先处理新任务(如实时性要求较高的场景)。
- 注意:可能丢失重要任务,需谨慎使用。
自定义拒绝策略
除了内置策略,可以通过实现 RejectedExecutionHandler
接口自定义拒绝逻辑。
public class CustomRejectionPolicy implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 自定义逻辑(如记录日志、暂存任务、重试等)
System.out.println("Task rejected: " + r);
}
}
如何设置拒绝策略?
在创建线程池时指定:
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize, // 核心线程数
maxPoolSize, // 最大线程数
keepAliveTime,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100), // 任务队列
new CustomRejectionPolicy() // 自定义拒绝策略
);