spring boot(17)-@Async异步

来源:互联网 发布:电动牙刷当跳蛋 知乎 编辑:程序博客网 时间:2024/06/16 00:12

验证码的异步机制


上一篇讲过可以用邮件发验证码,通常我们在某网站发验证码时,首先会提示验证码已发送,请检查邮箱或者短信,这就是图中的1和3。然而此时查看邮箱或短信可能并没有收到验证码,往往要过几秒种才真正收到,这就是图中的2和4。2和4所消耗的时间比1和3要多,如果是同步,先执行4后执行3,那么这个请求将一直占用后台服务器。如果是异步,可以在第一时间通知用户已发送,并释放请求,而完全不用去管2和4的执行过程。如果2和4执行不成功怎么办?在验证码提示消息结尾,我们经常可以看到:”如果你在XXX秒钟之内没有收到验证码,请重发“

@Async和@EnableAsync 实现异步

控制层
[java] view plain copy
  1. @GetMapping("/async")  
  2. public String test1() throws InterruptedException {  
  3.     helloService.task1();  
  4.     helloService.task2();  
  5.     System.out.println("释放请求");  
  6.     return "ok";  
  7. }  
服务层
[java] view plain copy
  1. @Async  
  2. public void task1() throws InterruptedException{  
  3.     Thread.sleep(2000);  
  4.     System.out.println("完成任务1");  
  5. }  
  6. @Async  
  7. public void task2() throws InterruptedException{  
  8.     Thread.sleep(1000);  
  9.     System.out.println("完成任务2");  
  10. }  
这是在一个控制层中调用了两个服务层的方法,任务1需要执行2秒时间,任务2需要执行1秒时间。和普通方法的唯一区别就是异步方法上加了@Async

上图是执行结果 ,这是同步。如果要让@Async异步生效还需要在配置类中开启异步,如下
[java] view plain copy
  1. @EnableAsync  
  2. @SpringBootApplication  
再次执行

执行顺序和前面完全颠倒,在第一时间就释放了请求,任务2和任务1是同时执行的,但是任务2时间短,所以比任务1先执行完。

应用场景

这个异步实际上就是spring封装了一个基本的多线程功能,每个@Async都会开启一个新的线程,并且 在内部使用了线程池。异步线程执行完后并没有回调方法得知任务是否执行成功,在一般的web场景下,异步回调是在前端用ajax的方式来实现的,一个页面可以有多个ajax,每个ajax去独立完成一个后台业务,谁先完成谁先响应,彼此互不干涉。后台业务则应该是彼此独立的以供ajax调用,如果在后台回调意味着多个业务任务整合到一个请求,而且这个请求的响应时间要按最慢的那个任务计算。所以这种后台异步只适用于对请求结果实时性要求不高的场景,不建议在后台使用回调。这也是我在第三篇Rest风格接口中讲过的,使用静态html+ajax,而不用动态jsp的原因之一。
原创粉丝点击