spring boot(17)-@Async异步

验证码的异步机制


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

@Async和@EnableAsync 实现异步

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

上图是执行结果 ,这是同步。如果要让@Async异步生效还需要在配置类中开启异步,如下
@EnableAsync
@SpringBootApplication
再次执行

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

应用场景

这个异步实际上就是spring封装了一个基本的多线程功能,每个@Async都会开启一个新的线程,并且 在内部使用了线程池。异步线程执行完后并没有回调方法得知任务是否执行成功,在一般的web场景下,异步回调是在前端用ajax的方式来实现的,一个页面可以有多个ajax,每个ajax去独立完成一个后台业务,谁先完成谁先响应,彼此互不干涉。后台业务则应该是彼此独立的以供ajax调用,如果在后台回调意味着多个业务任务整合到一个请求,而且这个请求的响应时间要按最慢的那个任务计算。所以这种后台异步只适用于发验证码之类 的特殊场景,不建议在后台 使用回调。这也是我在第三篇Rest风格接口中讲过的,使用静态html+ajax,而不用动态jsp的原因之一
posted @ 2017-08-26 10:12  free_java  阅读(1034)  评论(0编辑  收藏  举报