作用:
实现异步调用,如用在用户下单后发送微信模板消息等耗时操作
使用方法:
- 启动类加上@EnableAsync注解
* 启动类
*
*/
@EnableScheduling
@SpringBootApplication
@EnableTransactionManagement
@EnableAsync
public class App
{
public static void main( String[] args )
{
new SpringApplicationBuilder(App.class).run(args);
}
}
- 需被异步调用 的方法加上@Async注解
/**
* 被异步调用的方法
*/
@Async
public void aSync() throws InterruptedException {
Thread.sleep(3000);
System.out.println("测试3。。。。");
}
调用者
/**
* 调用者
*/
@RequestMapping("test")
public void test() throws InterruptedException {
System.out.println("测试1。。。。");
activityDao.aSync();
System.out.println("测试2。。。。");
}
- 执行结果:
-
注意:
- 在使用@Async的时候切记不要在同一个类里面调用@Async声明的方法,会产生代理绕过问题。
- 会出现这种 [info] 级别的日志: No task executor bean found for async processing: no bean of type TaskExecutor and no bean named 'taskExecutor' either
解决办法:
https://www.cnblogs.com/xsbx/p/10577409.html
https://juejin.im/post/5ab7ab936fb9a028df229651
配置类:
/**
* @author yz
* @className ThreadPoolConfig
* @description 线程池配置
* @date 2020/2/25 14:56
*/
@Configuration
@EnableAsync
public class ThreadPoolConfig {
/**
* 默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,
* 当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;
* 当队列满了,就继续创建线程,当线程数量大于等于maxPoolSize后,开始使用拒绝策略拒绝
*/
/** 核心线程数(默认线程数) */
private static final int CORE_POOL_SIZE = 20;
/** 最大线程数 */
private static final int MAX_POOL_SIZE = 100;
/** 允许线程空闲时间(单位:默认为秒) */
private static final int KEEP_ALIVE_TIME = 10;
/** 缓冲队列大小 */
private static final int QUEUE_CAPACITY = 200;
/** 线程池名前缀 */
private static final String THREAD_NAME_PREFIX = "Async-Service-";
@Bean("taskExecutor")
public ThreadPoolTaskExecutor taskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setMaxPoolSize(MAX_POOL_SIZE);
executor.setQueueCapacity(QUEUE_CAPACITY);
executor.setKeepAliveSeconds(KEEP_ALIVE_TIME);
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
// 线程池对拒绝任务的处理策略
// CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化
executor.initialize();
return executor;
}
}
检查配置是否生效,只要看日志打印的线程名前缀是否是自己配置的线程池前缀就行了:
参考资料: