springboot+async异步接⼝实现和调⽤
什么是异步调⽤?
异步调⽤是相对于同步调⽤⽽⾔的,同步调⽤是指程序按预定顺序⼀步步执⾏,每⼀步必须等到上⼀步执⾏完后才能执⾏,异步调⽤则⽆需等待上⼀步程序执⾏完即可执⾏。
如何实现异步调⽤?
多线程,这是很多⼈第⼀眼想到的关键词,没错,多线程就是⼀种实现异步调⽤的⽅式。
在⾮spring⽬项⽬中我们要实现异步调⽤的就是使⽤多线程⽅式,可以⾃⼰实现Runable接⼝或者集成Thread类,或者使⽤jdk1.5以上提供了的Executors线程池。
StrngBoot中则提供了很⽅便的⽅式执⾏异步调⽤。
异步接⼝的使⽤场景
耗时⽐较长,任务⽐较多的接⼝。⽐⽅说,⽂件下载,⼤⽂件下载⽐较耗时,这个时候就可以使⽤异步接⼝。
⽰例
代码⼊下
maven依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
启动类:添加@EnableAsync注解
@SpringBootApplication
@EnableAsync
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Controller
只需在需要异步执⾏⽅法上添加@Async注解
@RestController
@RequestMapping("")
public class AsyncTaskController {
@RequestMapping("")
public String doTask() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
this.task1();
this.task2();
this.task3();
long currentTimeMillis1 = System.currentTimeMillis();
return "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
}
public void task1() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
Thread.sleep(1000);
long currentTimeMillis1 = System.currentTimeMillis();
System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
}
@Async
public void task2() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
Thread.sleep(2000);
long currentTimeMillis1 = System.currentTimeMillis();
System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
}
@Async
public void task3() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
Thread.sleep(3000);
long currentTimeMillis1 = System.currentTimeMillis();
System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
}
}
main函数运⾏spirngboot项⽬,启动完成后浏览器访问:
控制台:
task1任务耗时:1012ms
task2任务耗时:2009ms
task3任务耗时:3004ms
等了⼀段浏览器时候输出⼊下:
task任务总耗时:6002ms
异步并没有执⾏!
难道是代码写错了?反复检查了好⼏遍,并没有发现什么明显错误,想起spring对@Transactional注解
springframework和springboot时也有类似问题,spring扫描时具有@Transactional注解⽅法的类时,是⽣成⼀个代理类,由代理类去开启关闭事务,⽽在同⼀个类中,⽅法调⽤是在类体内执⾏的,spring⽆法截获这个⽅法调⽤。
豁然开朗,将异步任务单独放到⼀个类中,调整代码⼊下:
Controller
@RequestMapping("")
@RestController
public class AsyncTaskController {
@Autowired
private AsyncTask asyncTask;
@RequestMapping("")
public String doTask() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
asyncTask.task1();
asyncTask.task2();
asyncTask.task3();
long currentTimeMillis1 = System.currentTimeMillis();
return "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
}
}
@Component
public class AsyncTask {
@Async
public void task1() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
Thread.sleep(1000);
long currentTimeMillis1 = System.currentTimeMillis();
System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
}
@Async
public void task2() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
Thread.sleep(2000);
long currentTimeMillis1 = System.currentTimeMillis();
System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
}
@Async
public void task3() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
Thread.sleep(3000);
long currentTimeMillis1 = System.currentTimeMillis();
System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
}
}
控制台:
task1任务耗时:1012ms
task2任务耗时:2009ms
task3任务耗时:3004ms
访问浏览器结果⼊下:
task任务总耗时:19ms
异步调⽤成功!
如何知道三个异步任务什么时候执⾏完,执⾏的结果怎样呢?可以采⽤添加Fature回调⽅式判断代码⼊下:
异步任务类
@Component
public class AsyncTask {
@Async
public Future<String> task1() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
Thread.sleep(1000);
long currentTimeMillis1 = System.currentTimeMillis();
System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
return new AsyncResult<String>("task1执⾏完毕");
}
@Async
public Future<String> task2() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
Thread.sleep(2000);
long currentTimeMillis1 = System.currentTimeMillis();
System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
return new AsyncResult<String>("task2执⾏完毕");
}
@Async
public Future<String> task3() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
Thread.sleep(3000);
long currentTimeMillis1 = System.currentTimeMillis();
System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
return new AsyncResult<String>("task3执⾏完毕");
}
}
Controller
@RequestMapping("")
@RestController
public class AsyncTaskController {
@Autowired
private AsyncTask asyncTask;
@RequestMapping("")
public String doTask() throws InterruptedException{
long currentTimeMillis = System.currentTimeMillis();
Future<String> task1 = asyncTask.task1();
Future<String> task2 = asyncTask.task2();
Future<String> task3 = asyncTask.task3();
String result = null;
for (;;) {
if(task1.isDone() && task2.isDone() && task3.isDone()) {
// 三个任务都调⽤完成,退出循环等待
break;
}
Thread.sleep(1000);
}
long currentTimeMillis1 = System.currentTimeMillis();
result = "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
return result;
}
}
控制台输出:
task1任务耗时:1000ms
task2任务耗时:2001ms
task3任务耗时:3001ms
浏览器输出:
<span >task任务总耗时:4015ms</span> 异步调⽤成功,并且在所有任务都完成时程序才返回了结果!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论