前言
本文主要給大家介紹了關(guān)于Spring Boot集成之異步調(diào)用Async的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧。
什么是異步調(diào)用?
異步調(diào)用是相對于同步調(diào)用而言的,同步調(diào)用是指程序按預(yù)定順序一步步執(zhí)行,每一步必須等到上一步執(zhí)行完后才能執(zhí)行,異步調(diào)用則無需等待上一步程序執(zhí)行完即可執(zhí)行。
異步處理方式
- 調(diào)用之后,不返回任何數(shù)據(jù)。
- 調(diào)用之后,返回數(shù)據(jù),通過Future來獲取返回數(shù)據(jù)
如何實(shí)現(xiàn)異步調(diào)用?
多線程,這是很多人第一眼想到的關(guān)鍵詞,沒錯,多線程就是一種實(shí)現(xiàn)異步調(diào)用的方式。
在非spring目項(xiàng)目中我們要實(shí)現(xiàn)異步調(diào)用的就是使用多線程方式,可以自己實(shí)現(xiàn)Runable接口或者集成Thread類,或者使用jdk1.5以上提供了的Executors線程池。
StrngBoot中則提供了很方便的方式執(zhí)行異步調(diào)用。
按照官方示例開擼
代碼入下
maven依賴:
1
2
3
4
5
6
7
8
9
10
11
|
<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注解
1
2
3
4
5
6
7
8
|
@SpringBootApplication @EnableAsync public class Application{ public static void main(String[] args) { SpringApplication.run(Application. class , args); } } |
Controller
只需在需要異步執(zhí)行方法上添加@Async注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
@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任務(wù)總耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ; } @Async public void task1() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep( 1000 ); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println( "task1任務(wù)耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ); } @Async public void task2() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep( 2000 ); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println( "task2任務(wù)耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ); } @Async public void task3() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep( 3000 ); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println( "task3任務(wù)耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ); } } |
main函數(shù)運(yùn)行spirngboot項(xiàng)目,啟動完成后瀏覽器訪問:http://localhost:8080/
控制臺:
1
2
3
|
task1任務(wù)耗時:1012ms task2任務(wù)耗時:2009ms task3任務(wù)耗時:3004ms |
等了一段瀏覽器時候輸出入下:
1
|
task任務(wù)總耗時:6002ms |
異步并沒有執(zhí)行!
難道是代碼寫錯了?反復(fù)檢查了好幾遍,并沒有發(fā)現(xiàn)什么明顯錯誤,想起spring對@Transactional注解時也有類似問題,spring掃描時具有@Transactional注解方法的類時,是生成一個代理類,由代理類去開啟關(guān)閉事務(wù),而在同一個類中,方法調(diào)用是在類體內(nèi)執(zhí)行的,spring無法截獲這個方法調(diào)用。
豁然開朗,將異步任務(wù)單獨(dú)放到一個類中,調(diào)整代碼入下:
Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@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任務(wù)總耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ; } } |
異步任務(wù)類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@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任務(wù)耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ); } @Async public void task2() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep( 2000 ); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println( "task2任務(wù)耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ); } @Async public void task3() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep( 3000 ); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println( "task3任務(wù)耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ); } } |
控制臺:
1
2
3
|
task1任務(wù)耗時:1012ms task2任務(wù)耗時:2009ms task3任務(wù)耗時:3004ms |
訪問瀏覽器結(jié)果入下:
1
|
task任務(wù)總耗時:19ms |
異步調(diào)用成功!
如何知道三個異步任務(wù)什么時候執(zhí)行完,執(zhí)行的結(jié)果怎樣呢?可以采用添加Fature回調(diào)方式判斷
代碼入下:
異步任務(wù)類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@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任務(wù)耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ); return new AsyncResult<String>( "task1執(zhí)行完畢" ); } @Async public Future<String> task2() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep( 2000 ); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println( "task2任務(wù)耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ); return new AsyncResult<String>( "task2執(zhí)行完畢" ); } @Async public Future<String> task3() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep( 3000 ); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println( "task3任務(wù)耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ); return new AsyncResult<String>( "task3執(zhí)行完畢" ); } } |
Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@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()) { // 三個任務(wù)都調(diào)用完成,退出循環(huán)等待 break ; } Thread.sleep( 1000 ); } long currentTimeMillis1 = System.currentTimeMillis(); result = "task任務(wù)總耗時:" +(currentTimeMillis1-currentTimeMillis)+ "ms" ; return result; } } |
控制臺輸出:
1
2
3
|
task1任務(wù)耗時:1000ms task2任務(wù)耗時:2001ms task3任務(wù)耗時:3001ms |
瀏覽器輸出:
1
|
task任務(wù)總耗時:4015ms |
異步調(diào)用成功,并且在所有任務(wù)都完成時程序才返回了結(jié)果!
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對服務(wù)器之家的支持。
原文鏈接:http://blog.csdn.net/v2sking/article/details/72795742