Bootstrap

SpringBoot线程池的自动化注入

SpringBoot的线程池的自动注入

本文适合会基本springboot工程创建的人

在这里插入图片描述

配置文件

pom.xml要导入的包

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!-- 为了读取配置文件 -->

application.yml

设置你需要的配置

thread:
  pool:
    executor:
      config:
        core-pool-size: 20
        max-pool-size: 200
        keep-alive-time: 10
        block-queue-size: 5000
        policy: CallerRunsPolicy

读取配置文件

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@ConfigurationProperties(prefix = "thread.pool.executor.config", ignoreInvalidFields = true)
public class ThreadPoolConfigProperties {

    /** 核心线程数 */
    private Integer corePoolSize = 20;
    /** 最大线程数 */
    private Integer maxPoolSize = 200;
    /** 最大等待时间 */
    private Long keepAliveTime = 10L;
    /** 最大队列数 */
    private Integer blockQueueSize = 5000;
    
    private String policy = "AbortPolicy";

}

prefix

读取文件中的前缀

ignoreInvalidFields字段含义

ignoreInvalidFields: 当这个属性设置为true时,Spring会忽略配置文件中那些与配置类字段不匹配的属性。这意味着,如果配置文件中存在与配置类字段不存在的属性,Spring不会抛出异常,而是忽略这些属性。

Policy属性

  • AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
  • DiscardPolicy:直接丢弃任务,但是不会抛出异常
  • DiscardOldestPolicy:将最早进入队列的任务删除,之后再尝试加入队列的任务被拒绝
  • CallerRunsPolicy:如果任务添加线程池失败,那么主线程自己执行该任务

创建实例

/** 开启异步 */
@EnableAsync
@Configuration
/** 填写之前读取配置那个类的类名 */
@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
public class ThreadPoolConfig {

    @Bean
    @ConditionalOnMissingBean(ThreadPoolExecutor.class)
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties properties) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        // 实例化策略
        RejectedExecutionHandler handler;
        switch (properties.getPolicy()){
            case "DiscardPolicy":
                handler = new ThreadPoolExecutor.DiscardPolicy();
                break;
            case "DiscardOldestPolicy":
                handler = new ThreadPoolExecutor.DiscardOldestPolicy();
                break;
            case "CallerRunsPolicy":
                handler = new ThreadPoolExecutor.CallerRunsPolicy();
                break;
            default:
                handler = new ThreadPoolExecutor.AbortPolicy();
                break;
        }
        // 创建线程池
        return new ThreadPoolExecutor(properties.getCorePoolSize(), 
                properties.getMaxPoolSize(),
                properties.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(properties.getBlockQueueSize()),
                Executors.defaultThreadFactory(),
                handler);
    }

}

@ConditionalOnMissingBean的作用

  1. 条件@ConditionalOnMissingBean 注解检查Spring容器中是否已经存在具有指定名称或类型的Bean。如果存在,则不会创建新的Bean。
  2. 名称:可以通过 name 属性指定Bean的名称。如果指定了名称,则只有当容器中不存在具有该名称的Bean时,才会创建新的Bean。
  3. 类型:可以通过 type 属性指定Bean的类型。如果指定了类型,则只有当容器中不存在该类型的Bean时,才会创建新的Bean。
  4. 组合条件:可以同时使用 nametype 属性来组合条件,确保只有同时满足名称和类型条件时才会创建Bean。
  5. 依赖条件:还可以使用 dependentOnBean 属性来指定一个依赖的Bean名称,只有当依赖的Bean存在时,才会创建新的Bean。

ThreadPoolExecutor参数含义

  • properties.getCorePoolSize(): 这个参数表示线程池的基本大小,即在没有任务执行时保持空闲的线程数量。
    含义: 在创建线程池时,会首先创建这个数量的线程。如果这些线程都忙于处理任务,那么线程池会根据需要创建更多线程,但不会超过最大线程数。

  • properties.getMaxPoolSize(): 这个参数表示线程池最大线程数。
    含义: 当所有核心线程都在执行任务时,线程池会创建额外的线程,直到达到这个最大值。超过这个数的线程会被拒绝执行。

  • properties.getKeepAliveTime(): 这个参数表示当线程没有任务执行时,保持空闲的最长时间。
    含义: 如果空闲线程超过这个时间,则线程会被终止。如果这个值设置为Long.MAX_VALUE,则空闲线程会一直保持活动状态。

  • TimeUnit.SECONDS: 这个参数表示keepAliveTime的时间单位。
    含义: 它指定了keepAliveTime参数的时间单位,在这个例子中是秒。

  • new LinkedBlockingQueue<>(properties.getBlockQueueSize()): 这个参数表示用于在线程池任务队列中存储等待执行的任务。
    含义: LinkedBlockingQueue是一个线程安全的无界队列,它适用于生产者-消费者场景。blockQueueSize是队列的容量,表示队列可以存储的最大任务数量。

  • Executors.defaultThreadFactory(): 这个参数表示线程池中线程的工厂。
    含义: Executors.defaultThreadFactory()提供默认的线程工厂,用于创建线程。默认线程工厂创建的线程没有特别的名称或组,并且具有非守护状态。

  • handler: 这个参数表示线程池中的任务拒绝策略。
    含义: 当线程池达到最大大小,无法继续添加新任务时,会调用拒绝策略。handler可以是ThreadPoolExecutor提供的四种拒绝策略。(上面有说)

导入使用

// 在你需要的地方导入,然后就可以使用了
@Autowired
ThreadPoolExecutor executor;
;