在一些后台耗时的场景比如说生成统计报表,生成数据文件,执行批量任务时候,需要异步执行,先登记信息,然后异步执行批量同步返回给客户端。在spring中要想使用异步方法执行,必须使用@EnableAsync注解开启async。
@Configuration
@EnableAsync
@ComponentScan(basePackages = {"com.cpx.service.async"})
public class AsyncConfig {
}
@Service
public class AsyncService {
@Async
public void exec(){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(LocalDateTime.now().toString() +":exec end");
}
}
添加@Async注解的方法必须是public的。方法所属的类必须是一个bean才能被扫描到。this方式调用异步方法是没有效果的。因为使用的动态代理。
测试方法的异步执行:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AsyncConfig.class);
AsyncService asyncService = (AsyncService) ctx.getBean("asyncService");
System.out.println(LocalDateTime.now().toString()+" start");
asyncService.exec();//该方法调用会异步执行
System.out.println(LocalDateTime.now().toString()+" main end");
ctx.close();
方法的异步执行是通过线程池来执行的, spring默认会从beanFactory中尝试去获取TaskExecutor类型的bean,如果获取不到,就会继续尝试获取bean name为’taskExecutor’的bean,还获取不到就创建一个SimpleAsyncTaskExecutor类型的执行器。SimpleAsyncTaskExecutor每来一个任务会启动一个Thread来执行任务,不会重复利用。这么看SimpleAsyncTaskExecutor不是一个严格意义的线程池,线程并不会重用。如果高并发耗时任务可能会导致一定的内存使用问题。这里可以指定线程池。
第一种通过实现AsyncConfigurer接口,然后重写getAsyncExecutor()方法。
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
//自定义线程池实现
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
}
这种线程池是所有@Async注解都可以使用,另一种可以在@Async(“taskExecutor”)注解上指定线程池名字。
返回值
@Async
public Future<String> exec(){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<String>("ok");
}
有返回的@Async方法异常会被封装到future里,没有返回值的可以定义一个AsyncUncaughtExceptionHandler来处理异常
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
System.out.println(method.getName()+",发生异常");
//TODO
}
}
然后在实现AsyncConfigurer的bean里重写getAsyncUncaughtExceptionHandler()返回自定义的异常handler。
异步执行的原理还是通过@EnableAsync引入对应的bean后置处理器,来使用advisor对@Async标识的方法进行代理增强。方法的执行会通过AsyncExecutionInterceptor代理执行。
原文地址:https://blog.csdn.net/sinat_16493273/article/details/134604035
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_5277.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!