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
的作用
- 条件:
@ConditionalOnMissingBean
注解检查Spring容器中是否已经存在具有指定名称或类型的Bean。如果存在,则不会创建新的Bean。 - 名称:可以通过
name
属性指定Bean的名称。如果指定了名称,则只有当容器中不存在具有该名称的Bean时,才会创建新的Bean。 - 类型:可以通过
type
属性指定Bean的类型。如果指定了类型,则只有当容器中不存在该类型的Bean时,才会创建新的Bean。 - 组合条件:可以同时使用
name
和type
属性来组合条件,确保只有同时满足名称和类型条件时才会创建Bean。 - 依赖条件:还可以使用
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;