使用@Async實現異步調用java
什麼是」異步調用」與」同步調用」spring
「同步調用」就是程序按照必定的順序依次執行,,每一行程序代碼必須等上一行代碼執行完畢才能執行;」異步調用」則是隻要上一行代碼執行,無需等待結果的返回就開始執行自己任務。 多線程
一般狀況下,」同步調用」執行程序所花費的時間比較多,執行效率比較差。因此,在代碼自己不存在依賴關係的話,咱們能夠考慮經過」異步調用」的方式來併發執行。併發
「異步調用」app
在 spring boot 框架中,只要提過@Async註解就能獎普通的同步任務改成異步調用任務。 框架
注意: @Async所修飾的函數不要定義爲static類型,這樣異步調用不會生效dom
1. 開啓@Async註解異步
在Spring Boot主類添加@EnableAsync註解async
2. 定義異步任務ide
定義Task類,建立三個處理函數分別模擬三個執行任務的操做,操做消耗時間隨機取(10秒內)。
@Component
public class Task {
//定義一個隨機對象.
public static Random random =new Random();
@Async //加入"異步調用"註解
public void doTaskOne() throws InterruptedException {
System.out.println("開始執行任務一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
System.out.println("完成任務一,耗時:" + (end - start) + "毫秒");
}
@Async
public void doTaskTwo() throws InterruptedException {
System.out.println("開始執行任務二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
System.out.println("完成任務二,耗時:" + (end - start) + "毫秒");
}
@Async
public void doTaaskThree() throws InterruptedException {
System.out.println("開始執行任務三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
System.out.println("完成任務三,耗時:" + (end - start) + "毫秒");
}
}
3. 建立Controller進行測試
注意@Autowired注入類,由於這個類已經被 Spring 管理了。若是使用 new 來得到線程類將不會執行異步效果,這裏涉及到在 Spring 中使用多線程。
@Controller
public class TaskController {
@Autowired
private Task TASK;
@ResponseBody
@RequestMapping("/task")
public String task() throws Exception {
System.out.println("開始執行Controller任務");
long start = System.currentTimeMillis();
TASK.doTaskOne();
TASK.doTaskTwo();
TASK.doTaaskThree();
long end = System.currentTimeMillis();
System.out.println("完成Controller任務,耗時:" + (end - start) + "毫秒");
return "success";
}
}
訪問 http://localhost:8080/task 截圖:
「同步調用」就是程序按照必定的順序依次執行,每一行程序代碼必須等上一行代碼執行完畢才能執行;」異步調用」則是隻要上一行代碼執行,無需等待結果的返回就開始執行自己任務。
一般狀況下,」同步調用」執行程序所花費的時間比較多,執行效率比較差。因此,在代碼自己不存在依賴關係的話,咱們能夠考慮經過」異步調用」的方式來併發執行。
在 spring boot 框架中,只要提過@Async註解就能獎普通的同步任務改成異步調用任務。
注意: @Async所修飾的函數不要定義爲static類型,這樣異步調用不會生效
在Spring Boot主類添加@EnableAsync註解,以下:
@SpringBootApplication
@EnableAsync // 啓用異步註解
@ComponentScan(basePackages="com.ideabook")
public class SpringbootStartApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringbootStartApplication.class, args);
}
}
定義Task類,建立三個處理函數分別模擬三個執行任務的操做,操做消耗時間隨機取(10秒內)。
@Service
public class AsyncService {
public static Random random =new Random();
@Async
public Future<String> doTaskOne() throws Exception {
System.out.println("開始作任務一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
System.out.println("完成任務一,耗時:" + (end - start) + "毫秒");
return new AsyncResult<>("任務一完成");
}
@Async
public Future<String> doTaskTwo() throws Exception {
System.out.println("開始作任務二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
System.out.println("完成任務二,耗時:" + (end - start) + "毫秒");
return new AsyncResult<>("任務二完成");
}
@Async
public Future<String> doTaskThree() throws Exception {
System.out.println("開始作任務三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
System.out.println("完成任務三,耗時:" + (end - start) + "毫秒");
return new AsyncResult<>("任務三完成");
}
@Async
public void doTaskFour(){
System.out.println("開始作任務四");
long start = System.currentTimeMillis();
long count = 0;
for (int i = 0 ; i < 10000000; i ++){
count = count + i ;
}
long end = System.currentTimeMillis();
System.out.println("完成任務四,耗時:" + (end - start) + "毫秒");
}
}
注意@Autowired注入類,由於這個類已經被 Spring 管理了。若是使用 new 來得到線程類將不會執行異步效果,這裏涉及到在 Spring 中使用多線程。
@Controller
@RequestMapping("/async")
public class AsyncController {
private AsyncService asyncService;
@Autowired
public AsyncController(AsyncService asyncService) {
this.asyncService = asyncService;
}
@RequestMapping("/test")
@ResponseBody
public String testAsync() throws Exception{
long start = System.currentTimeMillis();
Future<String> task1 = asyncService.doTaskOne();
Future<String> task2 = asyncService.doTaskTwo();
Future<String> task3 = asyncService.doTaskThree();
asyncService.doTaskFour();
while(true) { //等待功能所有完成後,再返回效果。相似於接口內部各個功能的異步執行,最後統一返回狀態值。
if(task1.isDone() && task2.isDone() && task3.isDone()) {
// 三個任務都調用完成,退出循環
break;
}
// Thread.sleep(1000);
}
long end = System.currentTimeMillis();
System.out.println("任務所有完成,總耗時:" + (end - start) + "毫秒");
return "Success!!";
}
}