Skip to content

Spring Boot 自定义异步线程池

异步任务处理是提高应用性能和响应速度的关键技术之一。Spring Boot 提供了 ThreadPoolTaskExecutor 作为线程池的实现,帮助开发者轻松管理和执行异步任务. 在项目中,我们发现有人在配置类中加上 @EnableAsync , 然后 application.yml 没有进行相关线程池的配置,这是一件非常危险的事,因为默认 ThreadPoolTaskExecutor 采用的是 缓冲队列的容量,默认为 INT 的最大值,许的最大线程数,默认为 INT 的最大值(2 的 31 次方-1),要是任务比较耗时,同时任务数量多的话就会造成内存溢出。

具体可以参考 TaskExecutionAutoConfiguration 配置类

application.yml 配置类有以下熟悉可以配置

yml
spring.task.execution.pool.core-size=2
spring.task.execution.pool.max-size=5
spring.task.execution.pool.queue-capacity=10
spring.task.execution.pool.keep-alive=60s
spring.task.execution.pool.allow-core-thread-timeout=true
spring.task.execution.shutdown.await-termination=false
spring.task.execution.shutdown.await-termination-period=
spring.task.execution.thread-name-prefix=task-

具体含义如下:

  • spring.task.execution.pool.core-size:线程池创建时的初始化线程数,默认为 8
  • spring.task.execution.pool.max-size:线程池的最大线程数,默认为 int 最大值
  • spring.task.execution.pool.queue-capacity:用来缓冲执行任务的队列,默认为 int 最大值
  • spring.task.execution.pool.keep-alive:线程终止前允许保持空闲的时间
  • spring.task.execution.pool.allow-core-thread-timeout:是否允许核心线程超时
  • spring.task.execution.shutdown.await-termination:是否等待剩余任务完成后才关闭应用
  • spring.task.execution.shutdown.await-termination-period:等待剩余任务完成的最大时间
  • spring.task.execution.thread-name-prefix:线程名的前缀

最佳实践

为了更好的进行线程池的管控,我们一般会自定义线程池,其次线程池隔离, 比如不同之间的线程池进行相互隔离, 下面介绍如何在 spring boot 中自定义线程池 starter 组件,这里只是把 starter 核心的代码放出来, 在企业组件中,我们还做了额外的工作,包括监控,动态线程池等。后续会开一个企业级 starter 组件合集,到时会详细介绍这部分内容

定义属性对象

java
@Data
@ConfigurationProperties(prefix = "async.config")
public class AsyncThreadPoolProperties {

    private int corePoolSize = Runtime.getRuntime().availableProcessors();

    private int maxPoolSize = Runtime.getRuntime().availableProcessors();

    private int keepAliveTime = 60;

    private int queueCapacity = 10000;

    private String threadPrefixName = "custom-thread-pool-";

}

定义配置类

java
@Configuration
@Slf4j
@EnableConfigurationProperties(value = {AsyncThreadPoolProperties.class})
public class ThreadPoolAutoConfiguration {


    @Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(AsyncThreadPoolProperties properties) {
        log.info("start custom async thread pool task executor begin with properties: {} ------", properties);
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(properties.getCorePoolSize());
        executor.setMaxPoolSize(properties.getMaxPoolSize());
        executor.setQueueCapacity(properties.getQueueCapacity());
        executor.setKeepAliveSeconds(properties.getKeepAliveTime());
        executor.setThreadNamePrefix(properties.getThreadPrefixName());
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

}

resources META-INF 创建 spring.factories 文件

写入以下内容

yml
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ssn.kit.thread.pool.ThreadPoolAutoConfiguration

测试

引入 starter

yml
<dependency>
<groupId>com.ssn.kit</groupId>
<artifactId>corp-kit-thread-pool</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

配置 application.yml

yml
async:
  config:
    max-pool-size: 4
    core-pool-size: 4
    queue-capacity: 500
    thread-prefix-name: thread-prefix

编写测试 service

java
@Component
@Slf4j
public class AsyncTask {


    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;

    public AsyncTask(ThreadPoolTaskExecutor threadPoolTaskExecutor) {
        this.threadPoolTaskExecutor = threadPoolTaskExecutor;
    }


    // 使用方式一, 特别要注意这个threadPoolTaskExecutor
    @Async("threadPoolTaskExecutor")
    public void executor() {
        log.info("executor service");
    }


    // 使用方式二
    public void submit() {
        threadPoolTaskExecutor.submit(() -> {
            log.info("executor submit service");
        });
    }

}

控制台日志

text
2024-11-13 14:59:22.935  INFO 19232 --- [ thread-prefix1] com.demo.pool.AsyncTask                  : executor service
2024-11-13 14:59:22.936  INFO 19232 --- [ thread-prefix2] com.demo.pool.AsyncTask                  : executor submit service

Released under the MIT License.