一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - Spring Boot集成教程之異步調(diào)用Async

Spring Boot集成教程之異步調(diào)用Async

2021-04-14 11:24再見尼羅河 Java教程

在項(xiàng)目中,當(dāng)訪問其他人的接口較慢或者做耗時任務(wù)時,不想程序一直卡在耗時任務(wù)上,想程序能夠并行執(zhí)行,我們可以使用多線程來并行的處理任務(wù),也可以使用spring提供的異步處理方式@Async。需要的朋友們下面來一起看看吧。

前言

本文主要給大家介紹了關(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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 草莓香蕉绿巨人丝瓜榴莲污在线观看 | 色哟哟哟 | 亚洲欧美日韩国产一区二区精品 | 欧美精品一区二区在线观看 | jiuse在线 | 厕所rxxx| 97精品国产高清在线看入口 | 香蕉在线精品亚洲第一区 | 美女班主任让我爽了一夜视频 | jzzjlzz亚洲乱熟在线播放 | 成人免费视频在 | 极品妖艳许清赵丽全文免费阅读 | 亚洲国产在线综合018 | 日韩aⅴ在线观看 | 亚洲第一福利视频 | ysav67| 色橹橹| 午色影院| 亚洲无线一二三四区 | 青青网| 继攵催眠女乱h调教 | 国产最强大片免费视频 | 精品国产在线观看 | 亚洲色图图| 蜜桃88av | 亚洲色图.com | 国产xxx在线| 91caoporm在线进入 | 新新电影理论中文字幕 | 齐天大性之七仙女欲春迅雷链接 | 欧美精品v日韩精品v国产精品 | 久久免费看少妇高潮A片2012 | 咪咪爱在线视频 | 亚洲精品m在线观看 | 96免费精品视频在线 | 久久国产视频网站 | 无码欧美喷潮福利XXXX | 99在线在线视频免费视频观看 | 亚洲精品高清中文字幕完整版 | 99久久99热久久精品免费看 | 处女摘花|