Spring Boot集成教程之異步調(diào)用Async
前言
本文主要給大家介紹了關(guān)于Spring Boot集成之異步調(diào)用Async的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧。
什么是異步調(diào)用?
異步調(diào)用是相對(duì)于同步調(diào)用而言的,同步調(diào)用是指程序按預(yù)定順序一步步執(zhí)行,每一步必須等到上一步執(zhí)行完后才能執(zhí)行,異步調(diào)用則無需等待上一步程序執(zhí)行完即可執(zhí)行。
異步處理方式
- 調(diào)用之后,不返回任何數(shù)據(jù)。
- 調(diào)用之后,返回?cái)?shù)據(jù),通過Future來獲取返回?cái)?shù)據(jù)
如何實(shí)現(xiàn)異步調(diào)用?
多線程,這是很多人第一眼想到的關(guān)鍵詞,沒錯(cuò),多線程就是一種實(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依賴:
<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>
啟動(dòng)類:添加@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ù)總耗時(shí):"+(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ù)耗時(shí):"+(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ù)耗時(shí):"+(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ù)耗時(shí):"+(currentTimeMillis1-currentTimeMillis)+"ms"); } }
main函數(shù)運(yùn)行spirngboot項(xiàng)目,啟動(dòng)完成后瀏覽器訪問:http://localhost:8080/
控制臺(tái):
task1任務(wù)耗時(shí):1012ms task2任務(wù)耗時(shí):2009ms task3任務(wù)耗時(shí):3004ms
等了一段瀏覽器時(shí)候輸出入下:
task任務(wù)總耗時(shí):6002ms
異步并沒有執(zhí)行!
難道是代碼寫錯(cuò)了?反復(fù)檢查了好幾遍,并沒有發(fā)現(xiàn)什么明顯錯(cuò)誤,想起spring對(duì)@Transactional注解時(shí)也有類似問題,spring掃描時(shí)具有@Transactional注解方法的類時(shí),是生成一個(gè)代理類,由代理類去開啟關(guān)閉事務(wù),而在同一個(gè)類中,方法調(diào)用是在類體內(nèi)執(zhí)行的,spring無法截獲這個(gè)方法調(diào)用。
豁然開朗,將異步任務(wù)單獨(dú)放到一個(gè)類中,調(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ù)總耗時(shí):"+(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ù)耗時(shí):"+(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ù)耗時(shí):"+(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ù)耗時(shí):"+(currentTimeMillis1-currentTimeMillis)+"ms"); } }
控制臺(tái):
task1任務(wù)耗時(shí):1012ms task2任務(wù)耗時(shí):2009ms task3任務(wù)耗時(shí):3004ms
訪問瀏覽器結(jié)果入下:
task任務(wù)總耗時(shí):19ms
異步調(diào)用成功!
如何知道三個(gè)異步任務(wù)什么時(shí)候執(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ù)耗時(shí):"+(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ù)耗時(shí):"+(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ù)耗時(shí):"+(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()) { // 三個(gè)任務(wù)都調(diào)用完成,退出循環(huán)等待 break; } Thread.sleep(1000); } long currentTimeMillis1 = System.currentTimeMillis(); result = "task任務(wù)總耗時(shí):"+(currentTimeMillis1-currentTimeMillis)+"ms"; return result; } }
控制臺(tái)輸出:
task1任務(wù)耗時(shí):1000ms task2任務(wù)耗時(shí):2001ms task3任務(wù)耗時(shí):3001ms
瀏覽器輸出:
task任務(wù)總耗時(shí):4015ms
異步調(diào)用成功,并且在所有任務(wù)都完成時(shí)程序才返回了結(jié)果!
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- 詳解SpringBoot中異步請(qǐng)求和異步調(diào)用(看完這一篇就夠了)
- Spring Boot利用@Async異步調(diào)用:使用Future及定義超時(shí)詳解
- Spring Boot利用@Async異步調(diào)用:ThreadPoolTaskScheduler線程池的優(yōu)雅關(guān)閉詳解
- Spring Boot利用@Async如何實(shí)現(xiàn)異步調(diào)用:自定義線程池
- 深入理解spring boot異步調(diào)用方式@Async
- spring boot 使用@Async實(shí)現(xiàn)異步調(diào)用方法
- spring boot中使用@Async實(shí)現(xiàn)異步調(diào)用任務(wù)
- SpringBoot異步調(diào)用方法實(shí)現(xiàn)場(chǎng)景代碼實(shí)例
相關(guān)文章
Java設(shè)計(jì)者模式簡(jiǎn)單工廠模式解析
這篇文章主要介紹了Java設(shè)計(jì)者模式簡(jiǎn)單工廠模式解析,介紹了其簡(jiǎn)介,實(shí)例以及優(yōu)缺點(diǎn)分析,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11Java編程實(shí)現(xiàn)調(diào)用com操作Word方法實(shí)例代碼
這篇文章主要介紹了Java編程實(shí)現(xiàn)調(diào)用com操作Word方法實(shí)例代碼,代碼注釋很詳細(xì),在這里分給大家,需要的朋友可以參考下。2017-09-09Spring中@RestControllerAdvice注解的使用詳解
這篇文章主要介紹了Spring中@RestControllerAdvice注解的使用詳解,@RestControllerAdvice是一個(gè)組合注解,由@ControllerAdvice、@ResponseBody組成,而@ControllerAdvice繼承了@Component,需要的朋友可以參考下2024-01-01詳解Java中方法重寫與重載的區(qū)別(面試高頻問點(diǎn))
這篇文章主要介紹了Java中方法重寫與重載的區(qū)別(面試高頻問點(diǎn)),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03springmvc模式的上傳和下載實(shí)現(xiàn)解析
這篇文章主要介紹了springmvc模式下的上傳和下載實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Java中如何快速構(gòu)建項(xiàng)目腳手架的實(shí)現(xiàn)
這篇文章主要介紹了Java中如何快速構(gòu)建項(xiàng)目腳手架,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05java實(shí)現(xiàn)Redisson的基本使用
Redisson是一個(gè)在Redis的基礎(chǔ)上實(shí)現(xiàn)的Java駐內(nèi)存數(shù)據(jù)網(wǎng)格客戶端,本文主要介紹了java實(shí)現(xiàn)Redisson的基本使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12Spring中使用自定義ThreadLocal存儲(chǔ)導(dǎo)致的坑及解決
這篇文章主要介紹了Spring中使用自定義ThreadLocal存儲(chǔ)導(dǎo)致的坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12