如何人为地触发ThreadPoolTaskExecutor线程池的拒绝策略,测试拒绝策略是否生效
要人为地触发 ThreadPoolTaskExecutor 的拒绝策略并测试其是否生效,可以通过以下步骤进行设置和操作:
- 限制线程池的核心线程数:将线程池的核心线程数和最大线程数设置为较小的值,这样更容易填满线程池中的线程。
- 限制任务队列的大小:将任务队列设置为较小的值,例如1,这样在提交任务时可以很快填满队列。
- 提交大量任务:通过循环或并发地提交任务,确保超过线程池的处理能力,从而触发拒绝策略。
具体步骤
1. 配置 ThreadPoolTaskExecutor
为了触发拒绝策略,需要先配置 ThreadPoolTaskExecutor,将线程池的核心线程数、最大线程数、队列容量设置得较小。
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class ThreadPoolTaskExecutorTest {
public static void main(String[] args) {
// 创建 ThreadPoolTaskExecutor 实例
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数(这里设为2)
executor.setCorePoolSize(2);
// 设置最大线程数(这里设为2)
executor.setMaxPoolSize(2);
// 设置队列容量(这里设为1)
executor.setQueueCapacity(1);
// 设置拒绝策略为 CallerRunsPolicy (可根据需求修改)
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化线程池
executor.initialize();
// 提交多个任务来触发拒绝策略
for (int i = 0; i < 5; i++) {
final int taskNumber = i;
executor.submit(() -> {
System.out.println("Running task " + taskNumber);
try {
// 模拟任务处理时间
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
System.out.println("Submitted task " + taskNumber);
}
// 关闭线程池
executor.shutdown();
}
}
2. 配置关键点解释:
- 核心线程数:设置为 2,这样同时只能有 2 个线程在处理任务。
- 最大线程数:设置为 2,确保线程池不会扩展超过 2 个线程。
- 队列容量:设置为 1,限制任务队列中只能有一个待处理的任务。
- 拒绝策略:设置为
CallerRunsPolicy。当线程池和任务队列都满时,新的任务会在提交的线程中运行,避免抛出异常。你也可以使用AbortPolicy来抛出异常测试。
3. 触发拒绝策略
在这个示例中,我们提交了 5 个任务,而线程池只能同时执行 2 个线程,队列只能容纳 1 个任务。当 3 个任务提交时,前两个会进入线程池执行,第三个会进入队列,接下来的两个任务会触发拒绝策略。
4. 观察输出和行为
运行代码后,可以观察到任务提交和执行的顺序。由于我们使用了 CallerRunsPolicy,在任务队列和线程池都满的时候,额外的任务会在提交任务的线程(即主线程)中执行。示例输出可能如下:
Submitted task 0
Running task 0
Submitted task 1
Running task 1
Submitted task 2
Submitted task 3
Running task 3 (this runs in the main thread due to CallerRunsPolicy)
Submitted task 4
5. 使用其他拒绝策略测试
如果想测试不同的拒绝策略,可以更改 RejectedExecutionHandler 设置,比如使用 AbortPolicy,当队列满了之后,提交任务将抛出 RejectedExecutionException:
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
运行上述代码时,超过容量的任务将导致异常:
Exception in thread "main" java.util.concurrent.RejectedExecutionException
总结
为了测试 ThreadPoolTaskExecutor 的拒绝策略,你可以通过:
- 设置小的核心线程数和最大线程数;
- 设置小的任务队列容量;
- 提交大量任务来填满线程池和队列;
从而触发拒绝策略,并观察不同策略的行为(比如抛出异常、在主线程运行等)。
浙公网安备 33010602011771号