@Async开启Spring异步调用
在springboot环境可以通过@EnableAsync + @Async
两个注解实现异步,必须使用@EnableAsync
开启,否则@Async
不会生效。
配置方式
使用JavaConfig简单配置:
@Configuration
@EnableAsync
public class DefaultAsyncConfig {
}
默认使用org.springframework.core.task.SimpleAsyncTaskExecutor
实现异步调用。
测试代码
@Component
public class TestService {
private static final Logger logger = LoggerFactory.getLogger(TestService.class);
@Async
public void testAsync(){
logger.info("Async Thread Name: {}", Thread.currentThread().getName());
}
}
结果如下,每次线程名称都会增加:
2021-03-09 09:45:51.950 INFO 14636 --- [task-1] c.c.m.p.h.service.connect.TestService : Async Thread Name: task-1
2021-03-09 09:46:09.953 INFO 14636 --- [task-2] c.c.m.p.h.service.connect.TestService : Async Thread Name: task-2
自定义线程池
按照上面的配置,已经实现了异步调用,不过每次调用实际上是生成一个新的线程,比较浪费服务器资源。一般需要自定义配置线程池,然后异步调用的时候从线程池中获取线程,配置如下:
@Configuration
@EnableAsync
public class DefaultAsyncConfig implements AsyncConfigurer {
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程数
executor.setCorePoolSize(10);
//最大线程数
executor.setMaxPoolSize(30);
//最大队列数
executor.setQueueCapacity(500);
//线程池中的线程的名称前缀
executor.setThreadNamePrefix("cloud-service-async-");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}
}
执行结果
2021-03-09 10:05:20.546 INFO 11372 --- [service-async-1] c.c.m.p.h.service.connect.TestService : Async Thread Name: cloud-service-async-1
2021-03-09 10:05:20.966 INFO 11372 --- [service-async-2] c.c.m.p.h.service.connect.TestService : Async Thread Name: cloud-service-async-2