spring的异步实现:@Async
1 通过注解@Async实现异步处理
在项目的启动类中加入注解@EnableAsync
在需要实现异步的方法上面加上注解@Async
以外露接口的形式,在controller层调用,就可以实现异步效果,代码如下
controller层代码:
@RestController public class AsyncController { private static final Logger logger = LoggerFactory.getLogger(AsyncController.class); @Autowired private IAsyncService asyncService; /** * 测试spring的异步调用顺序 * * @return */ @GetMapping("/async") public String asyncTest() { logger.info("************ 执行第一步 ************"); asyncService.sync(); asyncService.springAsync(); logger.info("************ 执行第二步 ************"); return "success"; } }
service层代码:
@Service public class AsyncServiceImpl implements IAsyncService { private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class); /** * spring的异步调用 */ @Async @Override public void springAsync() { logger.info("************ 执行异步start ************"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } logger.info("************ 执行异步end ************"); } /** * 同步方法 * * @return 执行结果 */ @Override public String sync() { logger.info("************ 执同步方法 start ************"); logger.info("************ 执同步方法 end ************"); return "success"; }
执行结果:从结果来看,程序先执行完controller层的代码,返回结果,然后才进行带有@Async的代码。实现了我们预期的效果
21:25:35.824 [http-nio-8815-exec-1] INFO c.s.c.c.AsyncController - [asyncTest,28] - ************ 执行第一步 ************ 21:25:35.824 [http-nio-8815-exec-1] INFO c.s.c.s.i.AsyncServiceImpl - [sync,39] - ************ 执同步方法 start ************ 21:25:35.824 [http-nio-8815-exec-1] INFO c.s.c.s.i.AsyncServiceImpl - [sync,40] - ************ 执同步方法 end ************ 21:25:35.827 [http-nio-8815-exec-1] INFO c.s.c.c.AsyncController - [asyncTest,31] - ************ 执行第二步 ************ 21:25:35.827 [task-1] INFO c.s.c.s.i.AsyncServiceImpl - [springAsync,23] - ************ 执行异步start ************ 21:25:38.829 [task-1] INFO c.s.c.s.i.AsyncServiceImpl - [springAsync,29] - ************ 执行异步end ************
2 直接在service层的同一个java文件中调用带有@Async注解的方法,不能实现异步效果。
controller层代码:
@RestController public class AsyncController { private static final Logger logger = LoggerFactory.getLogger(AsyncController.class); @Autowired private IAsyncService asyncService; /** * 测试spring的异步调用顺序 * * @return */ @GetMapping("/async") public String asyncTest() { logger.info("************ 执行第一步 ************"); asyncService.sync(); logger.info("************ 执行第二步 ************"); return "success"; } }
service层代码:
@Service public class AsyncServiceImpl implements IAsyncService { private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class); /** * spring的异步调用 */ @Async @Override public void springAsync() { logger.info("************ 执行异步start ************"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } logger.info("************ 执行异步end ************"); } /** * 同步方法 * * @return 执行结果 */ @Override public String sync() { logger.info("************ 执同步方法 start ************"); springAsync(); logger.info("************ 执同步方法 end ************"); return "success"; } }
执行结果:从结果来看,异步方法执行结束后才结束了一次请求,失去了异步的效果
21:05:15.397 [http-nio-8815-exec-1] INFO c.s.c.c.AsyncController - [asyncTest,28] - ************ 执行第一步 ************ 21:05:15.463 [http-nio-8815-exec-1] INFO c.s.c.s.i.AsyncServiceImpl - [sync,39] - ************ 执同步方法 start ************ 21:05:15.463 [http-nio-8815-exec-1] INFO c.s.c.s.i.AsyncServiceImpl - [springAsync,23] - ************ 执行异步start ************ 21:05:18.464 [http-nio-8815-exec-1] INFO c.s.c.s.i.AsyncServiceImpl - [springAsync,29] - ************ 执行异步end ************ 21:05:18.464 [http-nio-8815-exec-1] INFO c.s.c.s.i.AsyncServiceImpl - [sync,41] - ************ 执同步方法 end ************ 21:05:18.464 [http-nio-8815-exec-1] INFO c.s.c.c.AsyncController - [asyncTest,30] - ************ 执行第二步 ************
* 补充:何为同步异步?
同步:就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。
异步:则只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕;而是继续执行下面的流程。(在Java中,一般在处理类似的场景之时,都是基于创建独立的线程去完成相应的异步调用逻辑,通过主线程和不同的线程之间的执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。)
总结:同spring的事务类似。spring的事务是通过代理实现的,如果需要让事务生效,那么必须要走代理才可以。除了上述的方案之外,还可以进行将AsyncServiceImpl 自己注入自己,这样就也可以生效。
本文来自博客园,作者:zhangpba,转载请注明原文链接:https://www.cnblogs.com/zhangpb/p/14463942.html