JAVA中可以自己创建线程等多种方式来实现异步调用,在spring3.0中,引入了@Async注解,让开发者能够更方便的实现异步效果。下面来看看再SpringBoot中如何正确的使用异步调用。
一、启动类中,使用@EnableAsync注解开始异步功能
@SpringBootApplication
@EnableAsync
public class YCloudsServiceDemoApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication
.run(YCloudsServiceDemoApplication.class, args);
}
}
二、调用方
@RequestMapping("/test")
public ApiResp test() {
log.info("step: {}", 1);
testService.doTest();
log.info("step: {}", 4);
return ApiResp.retOK();
}
二、被调用方,用@Async注解标注需要异步执行的方法
@Override
@Async
public void doTest() {
log.info("step: {}", 2);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("step: {}", 3);
}
然后看看执行效果:
可以看到不是按照1234输出,而且线程名发生了改变,也就是说,已经实现了异步调用的效果。
========================================================================================
题外补充:
1、如果调用方,和异步方法在同一个类中,是不能实现异步调用的。
2、如果用@Async注解标识一个类的话,这个类的所有public方法都会变成异步的
3、我们可以通过实现AsyncConfigurer接口来定制化异步调用线程的配置。如线程名、线程池大小、甚至是异常处理
org.springframework.scheduling.annotation.AsyncConfigurer
@Slf4j
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setThreadNamePrefix("ThreadName-");
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
private class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
log.warn(throwable.getMessage(), throwable);
// 做一些你想做的事情
}
}
}