云南网站设计联系方式,如何做网站推广最有效,网络营销设计方案,天津网站制作哪个好在一些后台耗时的场景比如说生成统计报表#xff0c;生成数据文件#xff0c;执行批量任务时候#xff0c;需要异步执行#xff0c;先登记信息#xff0c;然后异步执行批量同步返回给客户端。在spring中要想使用异步方法执行#xff0c;必须使用EnableAsync注解开启async…在一些后台耗时的场景比如说生成统计报表生成数据文件执行批量任务时候需要异步执行先登记信息然后异步执行批量同步返回给客户端。在spring中要想使用异步方法执行必须使用EnableAsync注解开启async。
开启异步执行配置
Configuration
EnableAsync
ComponentScan(basePackages {com.cpx.service.async})
public class AsyncConfig {}然后在需要异步执行的方法上添加Async注解
Service
public class AsyncService {Asyncpublic 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();TaskExecutor
方法的异步执行是通过线程池来执行的 spring默认会从beanFactory中尝试去获取TaskExecutor类型的bean如果获取不到就会继续尝试获取bean name为’taskExecutor’的bean还获取不到就创建一个SimpleAsyncTaskExecutor类型的执行器。SimpleAsyncTaskExecutor每来一个任务会启动一个Thread来执行任务不会重复利用。这么看SimpleAsyncTaskExecutor不是一个严格意义的线程池线程并不会重用。如果高并发耗时任务可能会导致一定的内存使用问题。这里可以指定线程池。
第一种通过实现AsyncConfigurer接口然后重写getAsyncExecutor()方法。
public class AsyncConfig implements AsyncConfigurer {Overridepublic Executor getAsyncExecutor() {//自定义线程池实现ThreadPoolTaskExecutor threadPoolTaskExecutor new ThreadPoolTaskExecutor();threadPoolTaskExecutor.initialize();return threadPoolTaskExecutor;}
}这种线程池是所有Async注解都可以使用另一种可以在Async(“taskExecutor”)注解上指定线程池名字。
返回值
可以返回一个future。
Async
public FutureString exec(){try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return new AsyncResultString(ok);
}异常处理
有返回的Async方法异常会被封装到future里没有返回值的可以定义一个AsyncUncaughtExceptionHandler来处理异常
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {Overridepublic void handleUncaughtException(Throwable ex, Method method, Object... params) {System.out.println(method.getName(),发生异常);//TODO}
}然后在实现AsyncConfigurer的bean里重写getAsyncUncaughtExceptionHandler()返回自定义的异常handler。
异步执行的原理还是通过EnableAsync引入对应的bean后置处理器来使用advisor对Async标识的方法进行代理增强。方法的执行会通过AsyncExecutionInterceptor代理执行。