在启动类上添加@EnableAsync配合该注解使用
自定义线程池方法:
- implements AsyncConfigurer
- extends AsyncSupportConfigurer
- Bean 注入线程池
public interface AsyncConfigurer {
@Nullable
default Executor getAsyncExecutor() {
return null;
}
@Nullable
default AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
public class AsyncConfigurerSupport implements AsyncConfigurer {
public AsyncConfigurerSupport() {
}
public Executor getAsyncExecutor() {
return null;
}
@Nullable
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
都是在getAsyncExecutor方法种得到自定义线程池,不过还是得将线程池托管给bean,以便于spring可以管理线程池对象的生命周期。
第三种就是注入线程池bean:
@Bean
public ThreadPoolTaskExecutor executor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("Async-pool-");
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
如果bean不指定名字,将先从容器中检索Executor的bean,再找叫taskExecutor的bean,如果都没有找到则new一个SimpleAsyncTaskExecutor
SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,默认每次调用都会创建一个新的线程。
SyncTaskExecutor:这个类没有实现异步调用,只是一个同步操作。只适用于不需要多线程的地方。
ConcurrentTaskExecutor:Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类。
SimpleThreadPoolTaskExecutor:是Quartz的SimpleThreadPool的类。线程池同时被quartz和非quartz使用,才需要使用此类。
ThreadPoolTaskExecutor :最常使用,推荐。其实质是对java.util.concurrent.ThreadPoolExecutor的包装。
org.springframework.aop.interceptor.AsyncExecutionAspectSupport:
@Nullable
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
if (beanFactory != null) {
try {
return (Executor)beanFactory.getBean(TaskExecutor.class);
} catch (NoUniqueBeanDefinitionException var6) {
this.logger.debug("Could not find unique TaskExecutor bean. Continuing search for an Executor bean named 'taskExecutor'", var6);
try {
return (Executor)beanFactory.getBean("taskExecutor", Executor.class);
} catch (NoSuchBeanDefinitionException var4) {
if (this.logger.isInfoEnabled()) {
this.logger.info("More than one TaskExecutor bean found within the context, and none is named 'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly as an alias) in order to use it for async processing: " + var6.getBeanNamesFound());
}
}
} catch (NoSuchBeanDefinitionException var7) {
this.logger.debug("Could not find default TaskExecutor bean. Continuing search for an Executor bean named 'taskExecutor'", var7);
try {
return (Executor)beanFactory.getBean("taskExecutor", Executor.class);
} catch (NoSuchBeanDefinitionException var5) {
this.logger.info("No task executor bean found for async processing: no bean of type TaskExecutor and no bean named 'taskExecutor' either");
}
}
}
return null;
}
org.springframework.aop.interceptor.AsyncExecutionInterceptor:
@Nullable
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
// 先调用父类方法搜索bean 没有则new一个
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
return (Executor)(defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}
如果我们在定义线程池的时候没有给bean取名字,会去找一个taskExecutor的bean,可以使用
@Bean(AsyncExecutionAspectSupport.DEFAULT_TASK_EXECUTOR_BEAN_NAME)
指定名称,这样在@Async中不用指定线程池的名字
org.springframework.aop.interceptor.AsyncExecutionAspectSupport:
public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME = "taskExecutor";
线程池不指定名字的时候,有可能会出现bean容器中有多个线程池bean,然而@Async不知道要去用哪个,从而引发异常,业务失效。
所以最好是指定名称:
@Bean("asyncExecutor1")
public ThreadPoolTaskExecutor executor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("Async-pool-");
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
@Bean("asyncExecutor2")
public ThreadPoolTaskExecutor executor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("Async-pool2-");
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
@Async("asyncExecutor1")
public void speakNameByAsync(String name) {
}