异步任务在实际开发中经常会用到,我们通常将发邮件,推送等相对比较耗时的操作都是异步执行。大多数情况我们都是使用消息队列之类的方案解决。现在有一个简单的异步方案。
只需要两个步骤:
入口类添加@EnableAsync
注解
@EnableAsync
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
创建一个任务类:@Async
注解表明异步任务要执行的方法
package com.example.demo.task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
@Component
public class TestTask {
//异步任务此处必须返回Future,可以是Future<String>,也可以是Future<Integer>,自己定义具体的返回内容
@Async
public Future<String> test1() throws Exception{
Thread.sleep(1000);
System.out.println("执行任务1,用时1秒");
return new AsyncResult<>("test1");
}
@Async
public Future<String> test2() throws Exception{
Thread.sleep(1500);
System.out.println("执行任务2,用时1.5秒");
return new AsyncResult<>("test2");
}
}
这个类中有两个任务,test1() 和 test2(),为了模拟耗时的任务,两个方法分别sleep1秒和1.5秒。
如果是同步任务,执行这两个任务需要2.5秒左右。现在我们来测试一下异步的话是什么情况,写一个Controller触发任务执行:
package com.example.demo.controller;
import com.example.demo.task.TestTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.Future;
@RestController
public class HelloController {
@Autowired
private TestTask asyncTask;
@GetMapping("/hello")
public String hello() throws Exception{
long starttime = System.currentTimeMillis();
Future<String> task1 = asyncTask.test1();
Future<String> task2 = asyncTask.test2();
//等待任务都执行完
while(true){
if(task1.isDone() && task2.isDone()){
break;
}
}
long endtime = System.currentTimeMillis();
System.out.println("执行任务总用时:" + (endtime - starttime) + "毫秒");
return "";
}
}
上面方法中我们用了一个while循环来等待两个任务都执行完,实际上正常情况我们无需等待,否则异步任务就没有意义了。
启动springboot,然后通过浏览器访问,我们可以在控制台看到效果:
可以看到,如果是同步任务需要用时2.5秒,用了异步任务一共就用了1.5秒左右。