一文詳解SpringBoot如何優(yōu)雅地實(shí)現(xiàn)異步調(diào)用
前言
SpringBoot想必大家都用過(guò),但是大家平時(shí)使用發(fā)布的接口大都是同步的,那么你知道如何優(yōu)雅的實(shí)現(xiàn)異步呢?
這篇文章就是關(guān)于如何在Spring Boot
中實(shí)現(xiàn)異步行為的。但首先,讓我們看看同步和異步之間的區(qū)別。
- 同步編程:在同步編程中,任務(wù)一次執(zhí)行一個(gè),只有當(dāng)一個(gè)任務(wù)完成時(shí),下一個(gè)任務(wù)才會(huì)被解除阻塞。
- 異步編程:在異步編程中,可以同時(shí)執(zhí)行多個(gè)任務(wù)。您可以在上一個(gè)任務(wù)完成之前轉(zhuǎn)到另一個(gè)任務(wù)。
在Spring Boot
中,我們可以使用@Async
注解來(lái)實(shí)現(xiàn)異步行為。
實(shí)現(xiàn)步驟
1.定義一個(gè)異步服務(wù)接口AsyncService.java
public interface AsyncService { void asyncMethod() throws InterruptedException; Future<String> futureMethod() throws InterruptedException; }
2.實(shí)現(xiàn)定義的接口AsyncServiceImpl.java
@Service @Slf4j public class AsyncServiceImpl implements AsyncService { @Async @Override public void asyncMethod() throws InterruptedException { Thread.sleep(3000); log.info("Thread: [{}], Calling other service..", Thread.currentThread().getName()); } @Async @Override public Future<String> futureMethod() throws InterruptedException { Thread.sleep(5000); log.info("Thread: [{}], Calling other service..", Thread.currentThread().getName()); return new AsyncResult<>("task Done"); } }
AsyncServiceImpl
是一個(gè)spring
管理的bean
。- 您的異步方法必須是公共的,而且是被
@Async
注解修飾。 - 返回類型被限制為
void
或Future
。
3.定義一個(gè)控制器AsyncController.java
@EnableAsync @RestController @Slf4j public class AsyncController { @Autowired AsyncService asyncService; @GetMapping("/async") public String asyncCallerMethod() throws InterruptedException { long start = System.currentTimeMillis(); log.info("call async method, thread name: [{}]", Thread.currentThread().getName()); asyncService.asyncMethod(); String response = "task completes in :" + (System.currentTimeMillis() - start) + "milliseconds"; return response; } @GetMapping("/asyncFuture") public String asyncFuture() throws InterruptedException, ExecutionException { long start = System.currentTimeMillis(); log.info("call async method, thread name: [{}]", Thread.currentThread().getName()); Future<String> future = asyncService.futureMethod(); // 阻塞獲取結(jié)果 String taskResult = future.get(); String response = taskResult + "task completes in :" + (System.currentTimeMillis() - start) + "milliseconds"; return response; } }
- 關(guān)鍵點(diǎn),需要添加啟用異步的注解
@EnableAsync
,當(dāng)然這個(gè)注解加在其他地方也ok得。 - 當(dāng)外部調(diào)用該接口時(shí),
asyncMethod()
將由默認(rèn)任務(wù)執(zhí)行程序創(chuàng)建的另一個(gè)線程執(zhí)行,主線程不需要等待完成異步方法執(zhí)行。
4.運(yùn)行一下
現(xiàn)在我們運(yùn)行一下看看,是不是異步返回的。
可以看到調(diào)用/async
接口,最終一步調(diào)用了方法。
調(diào)用/asyncFuture
,發(fā)現(xiàn)返回5秒多,難道不是異步的嗎?其實(shí)也是異步的,看日志可以看出來(lái),只不過(guò)我們返回的是Future
,調(diào)用Futrue.get()
是阻塞的。
自定義異步任務(wù)執(zhí)行器和異常處理
我們現(xiàn)在看看如果異常方法中報(bào)錯(cuò)了會(huì)怎么樣?修改異步代碼如下所示,會(huì)拋運(yùn)行時(shí)異常:
再次執(zhí)行異步接口,如下所示,會(huì)使用默認(rèn)的線程池和異常處理。
我們也可以自定義異步方法的處理異常和異步任務(wù)執(zhí)行器,我們需要配置 AsyncUncaughtExceptionHandler
,如下代碼所示:
@Configuration public class AsynConfiguration extends AsyncConfigurerSupport { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(3); executor.setMaxPoolSize(4); executor.setThreadNamePrefix("asyn-task-thread-"); executor.setWaitForTasksToCompleteOnShutdown(true); executor.initialize(); return executor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new AsyncUncaughtExceptionHandler() { @Override public void handleUncaughtException(Throwable ex, Method method, Object... params) { System.out.println("Exception: " + ex.getMessage()); System.out.println("Method Name: " + method.getName()); ex.printStackTrace(); } }; } }
再次運(yùn)行,得到的結(jié)果如下:
@Async如何工作的
必須通過(guò)使用 @EnableAsync
注解注解主應(yīng)用程序類或任何直接或間接異步方法調(diào)用程序類來(lái)啟用異步支持。主要通過(guò)代理模式實(shí)現(xiàn),默認(rèn)模式是 Proxy
,另一種是 AspectJ
。代理模式只允許通過(guò)代理攔截調(diào)用。永遠(yuǎn)不要從定義它的同一個(gè)類調(diào)用異步方法,它不會(huì)起作用。
當(dāng)使用 @Async
對(duì)方法進(jìn)行注解時(shí),它會(huì)根據(jù)“proxyTargetClass
”屬性為該對(duì)象創(chuàng)建一個(gè)代理。當(dāng) spring
執(zhí)行這個(gè)方法時(shí),默認(rèn)情況下它會(huì)搜索關(guān)聯(lián)的線程池定義。上下文中唯一的 spring
框架 TaskExecutor bean
或名為“taskExecutor
”的 Executor bean
。如果這兩者都不可解析,默認(rèn)會(huì)使用spring框架SimpleAsyncTaskExecutor
來(lái)處理異步方法的執(zhí)行。
總結(jié)
在本文中,我們演示了在 spring boot 中如何使用 @Async
注解和異步方法中的異常處理實(shí)現(xiàn)異步行為。我們可以在一個(gè)接口中,需要訪問(wèn)不同的資源,比如異步調(diào)用各個(gè)其他服務(wù)的接口,可以使用@Async
,然后將結(jié)果通過(guò)Future
的方式阻塞匯總,不失為一個(gè)提高性能的好方法。
到此這篇關(guān)于一文詳解SpringBoot如何優(yōu)雅地實(shí)現(xiàn)異步調(diào)用的文章就介紹到這了,更多相關(guān)SpringBoot異步調(diào)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot 異步調(diào)用的實(shí)現(xiàn)方法
- SpringBoot實(shí)現(xiàn)定時(shí)任務(wù)和異步調(diào)用
- SpringBoot開(kāi)啟異步調(diào)用方法
- SpringBoot異步調(diào)用方法實(shí)現(xiàn)場(chǎng)景代碼實(shí)例
- springboot實(shí)現(xiàn)異步調(diào)用@Async的示例
- 三種SpringBoot中實(shí)現(xiàn)異步調(diào)用的方法總結(jié)
- SpringBoot使用@Async注解實(shí)現(xiàn)異步調(diào)用
- SpringBoot中的定時(shí)任務(wù)和異步調(diào)用詳解
- 淺談SpringBoot實(shí)現(xiàn)異步調(diào)用的幾種方式
相關(guān)文章
Java基本數(shù)據(jù)類型與對(duì)應(yīng)的包裝類(動(dòng)力節(jié)點(diǎn)java學(xué)院整理)
Java是面向?qū)ο蟮木幊陶Z(yǔ)言,包裝類的出現(xiàn)更好的體現(xiàn)這一思想,Java語(yǔ)言提供了八種基本類型。六種數(shù)字類型(四個(gè)整數(shù)型,兩個(gè)浮點(diǎn)型),一種字符類型,還有一種布爾型。 下面通過(guò)本文給大家詳細(xì)介紹,感興趣的朋友一起學(xué)習(xí)吧2017-04-04Java實(shí)戰(zhàn)之王者榮耀的英雄是怎么產(chǎn)生的?
這篇文章主要介紹了Java實(shí)戰(zhàn)之王者榮耀的英雄是怎么產(chǎn)生的?文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05Spring Security驗(yàn)證流程剖析及自定義驗(yàn)證方法
Spring Security是一個(gè)能夠?yàn)榛赟pring的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問(wèn)控制解決方案的安全框架。這篇文章主要介紹了Spring Security驗(yàn)證流程剖析及自定義驗(yàn)證方法,需要的朋友可以參考下2018-03-03SpringBoot多數(shù)據(jù)源配置的全過(guò)程記錄
在用SpringBoot開(kāi)發(fā)項(xiàng)目時(shí),隨著業(yè)務(wù)量的擴(kuò)大,我們通常會(huì)進(jìn)行數(shù)據(jù)庫(kù)拆分或是引入其他數(shù)據(jù)庫(kù),從而我們需要配置多個(gè)數(shù)據(jù)源,下面這篇文章主要給大家介紹了關(guān)于SpringBoot多數(shù)據(jù)源配置的相關(guān)資料,需要的朋友可以參考下2021-11-11Java的List集合框架之LinkedList詳細(xì)解析
這篇文章主要介紹了Java的List集合框架之LinkedList詳細(xì)解析,LinkedList底層是內(nèi)部Node類的存儲(chǔ),prev、next、item值,同時(shí)最外層還有first、last節(jié)點(diǎn),需要的朋友可以參考下2023-11-11SpringBoot整合FastDFS中間件實(shí)現(xiàn)文件分布管理
FastDFS是一個(gè)開(kāi)源的輕量級(jí)分布式文件系統(tǒng),它對(duì)文件進(jìn)行管理,功能包括:文件存儲(chǔ)、文件同步、文件上傳、文件下載等,解決了大容量存儲(chǔ)和負(fù)載均衡的問(wèn)題,本文介紹了SpringBoot整合FastDFS中間件實(shí)現(xiàn)文件分布管理,需要的朋友可以參考下2024-08-08