在現(xiàn)代的Web應用開發(fā)中,處理請求時需要考慮到系統(tǒng)的性能和響應速度。特別是在處理大量請求或者需要進行耗時操作時,采用異步多線程處理是一種常見的解決方案。Spring Boot提供了@Async注解來支持異步方法調(diào)用,結(jié)合合適的線程池配置,可以很容易地實現(xiàn)異步多線程處理,提升系統(tǒng)的并發(fā)能力和性能。
今日內(nèi)容介紹,大約花費9分鐘
圖片
@Configuration@EnableAsyncpublic class AsyncConfiguration { @Bean("doSomethingExecutor") public Executor doSomethingExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 核心線程數(shù):線程池創(chuàng)建時候初始化的線程數(shù) executor.setCorePoolSize(10); // 最大線程數(shù):線程池最大的線程數(shù),只有在緩沖隊列滿了之后才會申請超過核心線程數(shù)的線程 executor.setMaxPoolSize(20); // 緩沖隊列:用來緩沖執(zhí)行任務的隊列大小 executor.setQueueCapacity(500); // 允許線程的空閑時間60秒:當超過了核心線程之外的線程在空閑時間到達之后會被銷毀 executor.setKeepAliveSeconds(60); executor.setThreadNamePrefix("do-something-"); // 緩沖隊列滿了之后的拒絕策略:由調(diào)用線程處理(一般是主線程 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); executor.initialize(); return executor; }}
在這個配置中,我們使用了ThreadPoolTaskExecutor作為線程池的實現(xiàn),并且設置了一些關鍵參數(shù),如核心線程數(shù)、最大線程數(shù)、緩沖隊列大小等。如果不太了解線程池的小伙伴可以看一下之前介紹線程池介紹線程池的核心參數(shù),線程池的執(zhí)行原理知道
在需要異步執(zhí)行的方法上使用@Async注解。這樣的方法將會在一個單獨的線程中執(zhí)行,而不會阻塞主線程。
@Slf4j@Servicepublic class AsyncService { // 指定使用beanname為doSomethingExecutor的線程池 @Async("doSomethingExecutor") public CompletableFuture<String> doSomething(String message) throws InterruptedException { log.info("doSomethingExecutor thread name ={}", Thread.currentThread().getName()); Thread.sleep(1000); return CompletableFuture.completedFuture(message); }}
doSomething()方法被標記為異步方法,并且指定了使用名為"doSomethingExecutor"的線程池進行執(zhí)行。
在某些情況下,我們可能需要等待多個異步任務執(zhí)行完畢后再進行下一步操作,這時可以使用CompletableFuture來實現(xiàn)異步多結(jié)果的聚合。
@RestController@RequestMappingpublic class AsyncController { @Autowired private AsyncService asyncService; @GetMapping("/open/somethings") public List<String> somethings() throws InterruptedException { int count = 6; List<CompletableFuture<String>> futures = new ArrayList<>(); List<String> results = new ArrayList<>(); // 啟動多個異步任務,并將 CompletableFuture 對象存儲在列表中 for (int i = 1; i < count; i++) { CompletableFuture<String> future = asyncService.doSomething("index: "+i); futures.add(future); } for (CompletableFuture<String> future : futures) { String result = future.get(); // 阻塞等待異步任務完成并獲取結(jié)果 results.add(result); } return results; }}
我們通過循環(huán)啟動了多個異步任務,將返回的 CompletableFuture 對象存儲在列表中。然后,我們再次循環(huán)遍歷這些 CompletableFuture 對象,并調(diào)用 get() 方法來阻塞等待異步任務完成,獲取結(jié)果。最后,將結(jié)果添加到結(jié)果列表中并返回
使用瀏覽器發(fā)送http://localhost:8888/open/somethings,結(jié)果如下
圖片
發(fā)現(xiàn)使用多個線程執(zhí)行方法
圖片
@Async注解會在以下幾個場景失效,使用了@Async注解,但就沒有走多線程:
異步方法使用注解@Async的返回值只能為void或者Future及其子類,當返回結(jié)果為其他類型時,方法還是會異步執(zhí)行,但是返回值都是null
本文鏈接:http://www.www897cc.com/showinfo-26-80194-0.htmlSpringBoot中的異步多線程使用及避坑指南
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: vivo 消息中間件測試環(huán)境項目多版本實踐
下一篇: AI時代的技術棧,你了解幾分?