这个注解看着Async应该可以猜测用途,那就是异步。
这个注解是用来将某个被标注的方法给弄成异步的效果,达到new Thread的作用,
博主也赶紧拿来了代码测试。
异步我最先是在js学习时,ajax提交那里第一次接触,有一个async属性,来设置这个ajax是异步还是同步。
如下伪代码所示:
$(function(){
$.ajax({//1
async;true//设置为异步,代码应该不对,意思是这样
})
do something else;//2
});
js里的异步,就是这里的不需要ajax的请求得到返回结果,就可以执行2
而如果是同步,则是这里的async=false,必须ajax请求得到返回结果才能执行2
我就类比这里的ajax,认为@Async也是这个含义(经过试验,猜测正确)
@RequestMapping("/async")
public Object testAsync(String param){
System.out.println("controller 开始:"+new Timestamp(System.currentTimeMillis())+" "+param+ " thread:"+Thread.currentThread());
//开始异步方法执行
userService.async();
System.out.println("controller 返回 "+new Timestamp(System.currentTimeMillis())+"thread :"+Thread.currentThread());
return "finished";
}
public void async(){
long now=System.currentTimeMillis();
int count=0;
while (true){
if(count++==0){
System.out.println(System.currentTimeMillis()+" thread:"+Thread.currentThread());
}
if(System.currentTimeMillis()-5000>now){
System.out.println("异步方法:执行完成"+new Timestamp(System.currentTimeMillis())+ " thread:"+Thread.currentThread());
break;
}
}
}
5秒内调用两次接口:
// @Async controller 开始:2018-12-10 09:35:12.472 1 thread:Thread[http-nio-8011-exec-1,5,main]// 第一次调用 1544405712472 thread:Thread[http-nio-8011-exec-1,5,main]// 第一次调用 controller 开始:2018-12-10 09:35:13.863 1 thread:Thread[http-nio-8011-exec-2,5,main]//第二次调用 1544405713863 thread:Thread[http-nio-8011-exec-2,5,main]//第二次调用 异步方法:执行完成2018-12-10 09:35:17.473 thread:Thread[http-nio-8011-exec-1,5,main]// 第一次调用 controller 返回 2018-12-10 09:35:17.473thread :Thread[http-nio-8011-exec-1,5,main]// 第一次调用 异步方法:执行完成2018-12-10 09:35:18.864 thread:Thread[http-nio-8011-exec-2,5,main]//第二次调用 controller 返回 2018-12-10 09:35:18.864thread :Thread[http-nio-8011-exec-2,5,main]//第二次调用
结果说明什么:(按时间顺序)
第一次进入controller
第一次进入sync方法
第二次进入controller
第二次进入async方法
第一次退出async方法
第一次退出controller
第二次退出async方法
第二次退出controller
上述结果说明service的async方法没有被第一个线程独占,即第一下线程还在async方法中时,第二个也能同时进入。
并且controller方法的返回是出现在对应次的async方法退出之后再退出controller
但是这里的同步应该不是指async被线程独占,而是指 每次请求都是进入controller-》进入async方法-》退出async方法-》退出controller
需要注意的是:springboot需要在启动类上标注 @EnableAsync ,不然是不生效的
service方法:
@Async
public void async(){
long now=System.currentTimeMillis();
int count=0;
while (true){
if(count++==0){
System.out.println(System.currentTimeMillis()+" thread:"+Thread.currentThread());
}
if(System.currentTimeMillis()-5000>now){
System.out.println("异步方法:执行完成"+new Timestamp(System.currentTimeMillis())+ " thread:"+Thread.currentThread());
break;
}
}
}
controller 开始:2018-12-10 15:25:42.739 1 thread:Thread[http-nio-8011-exec-1,5,main]
controller 返回 2018-12-10 15:25:42.743thread :Thread[http-nio-8011-exec-1,5,main]
1544426742747 thread:Thread[task-1,5,main]
异步方法:执行完成2018-12-10 15:25:47.748 thread:Thread[task-1,5,main]
controller 开始:2018-12-10 15:25:48.602 1 thread:Thread[http-nio-8011-exec-3,5,main]
controller 返回 2018-12-10 15:25:48.602thread :Thread[http-nio-8011-exec-3,5,main]
1544426748603 thread:Thread[task-2,5,main]
异步方法:执行完成2018-12-10 15:25:53.604 thread:Thread[task-2,5,main]
发现了,的确是先完成了controller方法,而async方法还在继续,和js的ajax的异效果是一致的。
与不使用@Asyn对比发现;
不使用@Async:线程名字是: thread:Thread[http-nio-8011-exec-1,5,main] 是thread
使用@Async:线程名字是:1544426742747 thread:Thread[task-1,5,main] 是 task(多核线程,查看jdk源码定义,这个可以用来更新进度条的的作用,这里就不纠结了,是线程)
上面两种情况观察发现:
1,@Async达到的异步效果是ajax的那样
2,@Async开启了线程(Task)