线程池拒绝策略有哪些?
时间: 2025-06-30 16:08:36 浏览: 43
### Java 线程池拒绝策略的种类及其应用场景
#### 拒绝策略概述
Java 线程池通过 `ThreadPoolExecutor` 提供了一套灵活的任务调度机制。当线程池中的任务数量超过核心线程数且任务队列已满时,如果继续提交新任务,则需要由拒绝策略决定如何处理这些超出能力范围的任务[^1]。
#### 拒绝策略类型及特点
1. **AbortPolicy**
默认情况下使用的拒绝策略是 `AbortPolicy`。该策略会在尝试向线程池提交新任务失败时抛出 `RejectedExecutionException` 异常,从而阻止程序进一步运行。此策略适合于那些对任务丢失零容忍的应用场景,任何任务都无法丢弃的情况均适用[^2]。
2. **DiscardPolicy**
这种策略不会像 `AbortPolicy` 那样引发异常,而是默默地丢弃掉无法处理的新任务。因此,它适用于可以接受一定比例任务丢失的情形,比如后台批量处理作业等场合[^3]。
3. **DiscardOldestPolicy**
当线程池处于饱和状态时,`DiscardOldestPolicy` 会选择放弃最早进入队列等待的一个任务,并重新尝试提交当前任务直到成功为止。这种方法可能会影响较早到达的任务优先级,但它可以帮助缓解因突发高负载而导致的整体延迟增加问题[^1]。
4. **CallerRunsPolicy**
在启用 `CallerRunsPolicy` 后,一旦发生拒绝情况,主线程(调用者线程)将会亲自执行这个被拒任务而不是将其交给其他工作线程去完成。这通常用于希望降低新增加的工作量速度以防止系统过载崩溃的同时又不想完全忽略请求的情况下非常有用。
---
#### 示例代码展示
以下是一个关于自定义设置不同拒绝策略的小例子:
```java
import java.util.concurrent.*;
public class RejectedTaskDemo {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // corePoolSize
4, // maximumPoolSize
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(2), // bounded queue size of 2
Executors.defaultThreadFactory(),
getCustomRejectHandler()
);
for (int i = 0; i < 10; ++i) {
final int taskNum = i;
try {
executor.submit(() -> System.out.println("Running Task " + taskNum));
} catch (RejectedExecutionException e) {
System.err.println(e.getMessage());
}
}
Thread.sleep(500); // wait briefly before shutdown.
executor.shutdownNow();
}
private static RejectedExecutionHandler getCustomRejectHandler(){
return new ThreadPoolExecutor.CallerRunsPolicy(); // Replace this line with other policies as needed.
}
}
```
---
### 使用场景分析
- **AbortPolicy**: 对所有任务都极其敏感的服务端应用,不允许有任何单个任务因为资源不足而遭到忽视。
- **DiscardPolicy**: 处理大量非关键性的临时性任务集合时较为合适,即使有少量未能及时得到响应也不会造成严重影响。
- **DiscardOldestPolicy**: 平衡现有待办事项与最新到来之间的关系,在保证公平性和吞吐率之间寻找折衷方案。
- **CallerRunsPolicy**: 控制流入速率的有效手段之一,尤其在面对短时间内的流量激增现象特别有效果。
---
阅读全文
相关推荐




















