核心代码逻辑
/**
* 自定义线程池参数
*/
@Bean(name = "asyncThreadPool")
@Primary // 自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
@ConditionalOnClass(value = EnableAsync.class) // 有@EnableAysnc注解时加载该bean
public Executor getAsyncExecutor(){
log.info("[Async-Executor-init] - 线程池初始化");
//创建线程池包装对象 ThreadPoolTaskExecutor无需注册到注册 ContextClosedEvent,默认会等待该线程池销毁才会销毁bean
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//设置线程池参数
taskExecutor.setCorePoolSize(this.coreNum);//核心线程数
taskExecutor.setMaxPoolSize(this.maxNum);//最大线程数
taskExecutor.setKeepAliveSeconds(this.maxTimeoutSec);//空闲线程的最大存活时间
taskExecutor.setAllowCoreThreadTimeOut(this.allowCoreThreadTimeOut);//是否允许核心线程超时
taskExecutor.setRejectedExecutionHandler(this.rejectHandler.getRejectedExecutionHandler());//设置拒绝策略
taskExecutor.setThreadNamePrefix(this.threadNamePrefix);//设置线程名称的前缀
taskExecutor.setQueueCapacity(this.queueCapacity);//阻塞队列的最大容量
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);//开启在销毁线程池之前执行shutdown方法,false表示执行shutdownNow
taskExecutor.setAwaitTerminationSeconds(60);//设置通知关闭线程池后的等待时间
taskExecutor.initialize();
return taskExecutor;
}
补充
- 需要在启动类或配置类上加
@EnableAsync
注解,然后方可在方法上加@Async
注解标识这是一个异步方法; - 被
@Async
标注的方法只能被其他的bean调用才能生效,在同一个类中使用this不会生效,原因在于没有经过spring的动态代理; - 若想在关闭程序时,线程池中有任务在执行,在不设置
taskExecutor.setWaitForTasksToCompleteOnShutdown(true)
的情况下(该值默认为false),执行线程池的shutdownNow
方法,即立刻停止任务执行,并关闭线程池。设置该值为true时,执行线程池的shutdown
方法,即等待任务执行完关闭线程池,假如任务会阻塞的情况下,通过设置taskExecutor.setAwaitTerminationSeconds(60)
保证线程池在规定时间内会关闭; @Async
默认会使用自定义线程池,当然也可以通过@Async("asyncThreadPool")
指定,假如该线程池不存在会报错。没有指定线程池名称且没有自定义线程池时,使用spring默认线程池;