SpringBoot关于@Async线程池配置

我们在Spring项目的时候,会用到异步注解 @Async 注解,从 Spring原理之@Async 我们可以知道其实他底层用到的默认的所谓的线程池并不是真的线程池,每次调用都会创建一个新的线程,那么我们如何来修改这个默认的线程池或者说使用我们自定义的线程池呢?

1、修改@Async默认线程池

关于@Async的原理,可以查看 Spring原理之@Async 这篇博客,这里不在阐述

关于修改 @Async默认的线程池 ,我们仅仅需要实现一个 AsyncConfigurer 类,进行**getAsyncExecutor 方法 **的重写即可,具体例子如下:

@Slf4j
@EnableAsync //对应的@Enable注解,最好写在属于自己的配置文件上,保持内聚性
@Configuration
public class AsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10); //核心线程数
        executor.setMaxPoolSize(20);  //最大线程数
        executor.setQueueCapacity(1000); //队列大小
        executor.setKeepAliveSeconds(300); //线程最大空闲时间
        executor.setThreadNamePrefix("async-Executor-"); 指定用于新创建的线程名称的前缀。
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略(一共四种,此处省略)

        // 这一步千万不能忘了,否则报错: java.lang.IllegalStateException: ThreadPoolTaskExecutor not initialized
        executor.initialize();
        return executor;
    }
    
    // 异常处理器:当然你也可以自定义的,这里我就这么简单写了~~~
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return return new AsyncUncaughtExceptionHandler() {

            @Override
            public void handleUncaughtException(Throwable arg0, Method arg1, Object... arg2) {
                log.error("=========================="+arg0.getMessage()+"=======================", arg0);
                log.error("exception method:"+arg1.getName());
            }
        };
    }

}

具体使用:

@Component 
public class AsyncMyTask {    
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());     
    // 直接使用该注解即可
    @Async    
    public void doTask(int i) throws InterruptedException{        
        logger.info("Task-Native" + i + " started.");    
    } 
}

2、自定义线程池

我们可以自定义一个线程池,也是写一个配置类,在使用的时候,根据线程池的名称来使用具体的线程池

/**
 * 自定义创建线程池
 */
@Configuration
@EnableAsync
public class TaskExecutePool {
    @Bean
    public Executor myTaskAsyncPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10); //核心线程数
        executor.setMaxPoolSize(20);  //最大线程数
        executor.setQueueCapacity(1000); //队列大小
        executor.setKeepAliveSeconds(300); //线程最大空闲时间
        executor.setThreadNamePrefix("async-Executor-"); 指定用于新创建的线程名称的前缀。
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略(一共四种,此处省略)
        executor.initialize();
        return executor;
    }
}

使用:

@Component 
public class AsyncMyTask {    
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());     
    // 注解中标注使用的线程池是哪一个
    // myTaskAsynPool即配置线程池的方法名,此处如果不写自定义线程池的方法名,会使用默认的线程池
    @Async("myTaskAsyncPool")
    public void doTask(int i) throws InterruptedException{        
        logger.info("Task-Native" + i + " started.");    
    } 
}

如果想通过配置文件来对线程池中的属性进行方便修改的话:

(1)配置文件中进行配置

task.pool.corePoolSize=20
task.pool.maxPoolSize=40
task.pool.keepAliveSeconds=300
task.pool.queueCapacity=50

(2)编写获取配置属性的配置类

/**

线程池配置属性类
*/
@ConfigurationProperties(prefix = "task.pool")
@Data
public class ThreadPoolConfig {
    private int corePoolSize;

    private int maxPoolSize;

    private int keepAliveSeconds;

    private int queueCapacity;
}

(3)使用线程池配置属性类

/**
 * 创建线程池
*/
   @Configuration
   @EnableAsync
   public class TaskExecutePool {
       @Autowired
       private ThreadPoolConfig config;

       @Bean
       public Executor myTaskAsyncPool() {
           ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
           //核心线程池大小
           executor.setCorePoolSize(config.getCorePoolSize());
           //最大线程数
           executor.setMaxPoolSize(config.getMaxPoolSize());
           //队列容量
           executor.setQueueCapacity(config.getQueueCapacity());
           //活跃时间
           executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
           //线程名字前缀
           executor.setThreadNamePrefix("async-Executor-");
           // 拒绝策略
           executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
           executor.initialize();
           return executor;
       }
   }