最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2018年03月22日 11:12:09   作者:再見尼羅河  
在項目中,當(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目項目中我們要實(shí)現(xiàn)異步調(diào)用的就是使用多線程方式,可以自己實(shí)現(xiàn)Runable接口或者集成Thread類,或者使用jdk1.5以上提供了的Executors線程池。

StrngBoot中則提供了很方便的方式執(zhí)行異步調(diào)用。

按照官方示例開擼

代碼入下

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

只需在需要異步執(zhí)行方法上添加@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任務(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項目,啟動完成后瀏覽器訪問:http://localhost:8080/

控制臺:

task1任務(wù)耗時:1012ms 
task2任務(wù)耗時:2009ms 
task3任務(wù)耗時:3004ms 

等了一段瀏覽器時候輸出入下:

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

@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ù)類

@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"); 
 } 
} 

控制臺:

task1任務(wù)耗時:1012ms 
task2任務(wù)耗時:2009ms 
task3任務(wù)耗時:3004ms 

訪問瀏覽器結(jié)果入下:

task任務(wù)總耗時:19ms 

異步調(diào)用成功!

如何知道三個異步任務(wù)什么時候執(zhí)行完,執(zhí)行的結(jié)果怎樣呢?可以采用添加Fature回調(diào)方式判斷

代碼入下:

異步任務(wù)類

@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

@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; 
 } 
} 

控制臺輸出:

task1任務(wù)耗時:1000ms 
task2任務(wù)耗時:2001ms 
task3任務(wù)耗時:3001ms 

瀏覽器輸出:

task任務(wù)總耗時:4015ms

異步調(diào)用成功,并且在所有任務(wù)都完成時程序才返回了結(jié)果!

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • springboot整合mybatis-plus基于注解實(shí)現(xiàn)一對一(一對多)查詢功能

    springboot整合mybatis-plus基于注解實(shí)現(xiàn)一對一(一對多)查詢功能

    這篇文章主要介紹了springboot整合mybatis-plus基于純注解實(shí)現(xiàn)一對一(一對多)查詢功能,因為本人采用的是spring-boot進(jìn)行開發(fā),本身springboot就提倡采用不用配置自動配置的方式,所以真心希望mybatis(不是mybatis-plus)這點(diǎn)需要繼續(xù)努力
    2021-09-09
  • Java?精煉解讀數(shù)據(jù)結(jié)構(gòu)的鏈表的概念與實(shí)現(xiàn)

    Java?精煉解讀數(shù)據(jù)結(jié)構(gòu)的鏈表的概念與實(shí)現(xiàn)

    鏈表是一種物理存儲單元上非連續(xù)、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針連接次序?qū)崿F(xiàn)的,每一個鏈表都包含多個節(jié)點(diǎn),節(jié)點(diǎn)又包含兩個部分,一個是數(shù)據(jù)域,一個是引用域
    2022-03-03
  • java中File與MultipartFile互轉(zhuǎn)代碼示例

    java中File與MultipartFile互轉(zhuǎn)代碼示例

    在Java開發(fā)中,當(dāng)需要將本地File對象轉(zhuǎn)換為MultipartFile對象以處理文件上傳時,可以通過實(shí)現(xiàn)MultipartFile接口或使用CommonsMultipartFile類來實(shí)現(xiàn),本文提供了詳細(xì)的轉(zhuǎn)換方法和代碼示例,需要的朋友可以參考下
    2024-10-10
  • SpringBoot 應(yīng)用程序測試實(shí)現(xiàn)方案

    SpringBoot 應(yīng)用程序測試實(shí)現(xiàn)方案

    這篇文章主要介紹了SpringBoot 應(yīng)用程序測試實(shí)現(xiàn)方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • IDEA 非常重要的一些設(shè)置項(一連串的問題差點(diǎn)讓我重新用回 Eclipse)

    IDEA 非常重要的一些設(shè)置項(一連串的問題差點(diǎn)讓我重新用回 Eclipse)

    這篇文章主要介紹了IDEA 非常重要的一些設(shè)置項(一連串的問題差點(diǎn)讓我重新用回 Eclipse),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • java使用elasticsearch分組進(jìn)行聚合查詢過程解析

    java使用elasticsearch分組進(jìn)行聚合查詢過程解析

    這篇文章主要介紹了java使用elasticsearch分組進(jìn)行聚合查詢過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • java中關(guān)于深拷貝的幾種方式總結(jié)

    java中關(guān)于深拷貝的幾種方式總結(jié)

    這篇文章主要介紹了java中關(guān)于深拷貝的幾種方式總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 詳解使用@RequestBody取POST方式的json字符串

    詳解使用@RequestBody取POST方式的json字符串

    這篇文章主要介紹了詳解使用@RequestBody取POST方式的json字符串,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 有關(guān)Java中的BeanInfo介紹

    有關(guān)Java中的BeanInfo介紹

    Java的BeanInfo在工作中并不怎么用到,我也是在學(xué)習(xí)spring源碼的時候,發(fā)現(xiàn)SpringBoot啟動時候會設(shè)置一個屬叫"spring.beaninfo.ignore",網(wǎng)上一些地方說這個配置的意思是是否跳過java BeanInfo的搜索,但是BeanInfo又是什么呢?本文我們將對此做一個詳細(xì)介紹
    2021-09-09
  • Spring Boot + Kotlin整合MyBatis的方法教程

    Spring Boot + Kotlin整合MyBatis的方法教程

    前幾天由于工作需要,便開始學(xué)習(xí)了kotlin,java基礎(chǔ)扎實(shí)學(xué)起來也還算比較快,對于kotlin這個編程語言自然是比java有趣一些,下面這篇文章主要給大家介紹了關(guān)于Spring Boot + Kotlin整合MyBatis的方法教程,需要的朋友可以參考下。
    2018-01-01

最新評論

平潭县| 上杭县| 苏尼特左旗| 墨脱县| 丘北县| 涿鹿县| 通城县| 蓬安县| 县级市| 安达市| 麻栗坡县| 靖宇县| 石家庄市| 青浦区| 浑源县| 朔州市| 来宾市| 枝江市| 浮梁县| 河北区| 大埔县| 铜梁县| 芒康县| 库伦旗| 乡城县| 邢台市| 天峨县| 乌拉特后旗| 万山特区| 东辽县| 小金县| 军事| 洛阳市| 屏东县| 上饶县| 潼南县| 稻城县| 罗定市| 玉溪市| 双牌县| 建阳市|