如何人为地触发ThreadPoolTaskExecutor线程池的拒绝策略,测试拒绝策略是否生效

要人为地触发 ThreadPoolTaskExecutor 的拒绝策略并测试其是否生效,可以通过以下步骤进行设置和操作:

  1. 限制线程池的核心线程数:将线程池的核心线程数和最大线程数设置为较小的值,这样更容易填满线程池中的线程。
  2. 限制任务队列的大小:将任务队列设置为较小的值,例如1,这样在提交任务时可以很快填满队列。
  3. 提交大量任务:通过循环或并发地提交任务,确保超过线程池的处理能力,从而触发拒绝策略。

具体步骤

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 的拒绝策略,你可以通过:

  • 设置小的核心线程数和最大线程数;
  • 设置小的任务队列容量;
  • 提交大量任务来填满线程池和队列;
    从而触发拒绝策略,并观察不同策略的行为(比如抛出异常、在主线程运行等)。
posted @ 2024-10-10 02:08  gongchengship  阅读(40)  评论(0)    收藏  举报