SpringBoot異步調(diào)用方法實(shí)現(xiàn)場景代碼實(shí)例
一、背景
項(xiàng)目中肯定會遇到異步調(diào)用其他方法的場景,比如有個計(jì)算過程,需要計(jì)算很多個指標(biāo)的值,但是每個指標(biāo)計(jì)算的效率快慢不同,如果采用同步執(zhí)行的方式,運(yùn)行這一個過程的時間是計(jì)算所有指標(biāo)的時間之和。比如:
方法A:計(jì)算指標(biāo)x,指標(biāo)y,指標(biāo)z的值,其中計(jì)算指標(biāo)x需要1s,計(jì)算指標(biāo)y需要2s,指標(biāo)z需要3s。最終執(zhí)行完方法A就是5s。
現(xiàn)在用異步的方式優(yōu)化一下
方法A異步調(diào)用方法B,方法C,方法D,方法B,方法C,方法D分別計(jì)算指標(biāo)x,指標(biāo)y,指標(biāo)z的值,那么最終執(zhí)行完方法A的時間則是3s。
還有一種用途是當(dāng)一個業(yè)務(wù)里面需要多個請求時,這時候異步并發(fā)請求所得到的回報遠(yuǎn)遠(yuǎn)是物有所值的。因?yàn)樗钱惒綀?zhí)行的,話不多說,一下是在springBoot里面使用并發(fā)請求;
二、spring boot中異步并發(fā)使用
2.1、appllication.yml
#****************集成Async線程池開始******************* async: # Async線程池 配置 executor: corepoolsize: 20 maxpoolsize: 25 queuecapacity: 40 keepaliveseconds: 200 threadnameprefix: appasync awaitterminationseconds: 60 #*****************集成Async線程池結(jié)束******************
2.2、配置線程池
@Configuration @EnableAsync public class ExecutorConfig { @Value("${async.executor.corepoolsize}") private Integer corePoolSize; @Value("${async.executor.maxpoolsize}") private Integer maxPoolSize; @Value("${async.executor.queuecapacity}") private Integer queueCapacity; @Value("${async.executor.keepaliveseconds}") private Integer keepAliveSeconds; @Value("${async.executor.threadnameprefix}") private String threadNamePrefix; @Value("${async.executor.awaitterminationseconds}") private Integer awaitTerminationSeconds; /** * 線程池 * * @return */ @Bean(name = "asyncExecutor") public Executor asyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 基礎(chǔ)線程數(shù) corePoolSize: 10 executor.setCorePoolSize(corePoolSize); // 最大線程數(shù) maxPoolSize: 15 executor.setMaxPoolSize(maxPoolSize); // 隊(duì)列長度 queueCapacity: 25 executor.setQueueCapacity(queueCapacity); // 線程池維護(hù)線程所允許的空閑時間,單位為秒 keepAliveSeconds: 200 executor.setKeepAliveSeconds(keepAliveSeconds); // 線程名字 threadNamePrefix: appasync executor.setThreadNamePrefix(threadNamePrefix); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待所有任務(wù)都完成再繼續(xù)銷毀其他的Bean executor.setWaitForTasksToCompleteOnShutdown(true); // 線程池中任務(wù)的等待時間,如果超過這個時候還沒有銷毀就強(qiáng)制銷毀,以確保應(yīng)用最后能夠被關(guān)閉,而不是阻塞住 executor.setAwaitTerminationSeconds(awaitTerminationSeconds); executor.initialize(); return executor; } }
2.3、線程池監(jiān)控(這個可有可無,主要是為了對線程池參數(shù)及時的調(diào)優(yōu))
@RestController @Slf4j @RequestMapping("/pubapi/asyncExecutor") public class AsyncExecutorController extends BaseController { @Resource(name = "asyncExecutor") private Executor asyncExecutor; @PostMapping("/monitor")public ResultBean<Map<String, Object>> getAsyncExecutorData() { ResultBean<Map<String, Object>> resultBean = ResultBeanUtil.error500(); if (asyncExecutor == null) { return resultBean; } try { ThreadPoolTaskExecutor executorTask = (ThreadPoolTaskExecutor) asyncExecutor; ThreadPoolExecutor executor = executorTask.getThreadPoolExecutor(); // 當(dāng)前排隊(duì)線程數(shù) int queueSize = executor.getQueue().size(); // 當(dāng)前活動線程數(shù) int activeCount = executor.getActiveCount(); // 執(zhí)行完線程數(shù) long completedThreadCount = executor.getCompletedTaskCount(); // 總線程數(shù) long taskCount = executor.getTaskCount(); // 初始線程數(shù) int poolSize = executor.getPoolSize(); // 核心線程數(shù) int corePoolSize = executor.getCorePoolSize(); // 線程池是否終止 boolean isTerminated = executor.isTerminated(); // 線城池是否關(guān)閉 boolean isShutdown = executor.isShutdown(); // 線程空閑時間 long keepAliveTime = executor.getKeepAliveTime(TimeUnit.MILLISECONDS); // 最大允許線程數(shù) long maximumPoolSize = executor.getMaximumPoolSize(); // 線程池中存在的最大線程數(shù) long largestPoolSize = executor.getLargestPoolSize(); Map<String, Object> threadPoolData = new HashMap<>(18); threadPoolData.put("當(dāng)前排隊(duì)線程數(shù)", queueSize); threadPoolData.put("當(dāng)前活動線程數(shù)", activeCount); threadPoolData.put("執(zhí)行完線程數(shù)", completedThreadCount); threadPoolData.put("總線程數(shù)", taskCount); threadPoolData.put("初始線程數(shù)", poolSize); threadPoolData.put("核心線程數(shù)", corePoolSize); threadPoolData.put("線程池是否終止", isTerminated); threadPoolData.put("線城池是否關(guān)閉", isShutdown); threadPoolData.put("線程空閑時間", keepAliveTime); threadPoolData.put("最大允許線程數(shù)", maximumPoolSize); threadPoolData.put("線程池中存在的最大線程數(shù)", largestPoolSize); InetAddress inetAddress = IdWorker.getLocalHostLANAddress(); Map<String, Object> resultData = new HashMap<>(4); resultData.put("ip", inetAddress.getHostAddress()); resultData.put("threadPoolData", threadPoolData); resultBean = ResultBeanUtil.success("請求成功!", resultData); } catch (Exception e) { e.printStackTrace(); } return resultBean; } }
2.4、代碼中使用
public void getMap(){ /** * 先將耗時的、相互之間無依賴的操作先執(zhí)行,由于其執(zhí)行結(jié)果暫時不是特別關(guān)注,所以 */ Future<String> futureA = functionA(); Future<String> futureB = functionB(); /** * 執(zhí)行其他的操作,其實(shí)functionA(),functionB()也在工作 */ aaa(); /** * 獲取異步的結(jié)果,然后計(jì)算 */ try { String resultA =futureA.get(); String resuleB = futureB.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } public Future<String> functionA (){ Future<String> future = null; try { Thread.sleep(5000); future = new AsyncResult<String>("functionA"); } catch (InterruptedException e) { e.printStackTrace(); } return future; } public Future<String> functionB (){ Future<String> future = null; try { Thread.sleep(3000); future = new AsyncResult<String>("functionB"); } catch (InterruptedException e) { e.printStackTrace(); } return future; } public void aaa(){ System.out.println("我是"); }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringBoot開啟異步調(diào)用方法
- 淺析SpringBoot微服務(wù)中異步調(diào)用數(shù)據(jù)提交數(shù)據(jù)庫的問題
- 三種SpringBoot中實(shí)現(xiàn)異步調(diào)用的方法總結(jié)
- SpringBoot使用@Async注解實(shí)現(xiàn)異步調(diào)用
- 淺談SpringBoot實(shí)現(xiàn)異步調(diào)用的幾種方式
- SpringBoot中異步調(diào)用時的注意事項(xiàng)
- SpringBoot中使用@Async實(shí)現(xiàn)異步任務(wù)調(diào)用詳解
- SpringBoot實(shí)現(xiàn)異步調(diào)用的方法示例
相關(guān)文章
java中的FileInputStream三種read()函數(shù)用法
這篇文章主要介紹了java中的FileInputStream三種read()函數(shù)用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12解決idea默認(rèn)帶的equals和hashcode引起的bug
這篇文章主要介紹了解決idea默認(rèn)帶的equals和hashcode引起的bug,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07SpringBoot+vue實(shí)現(xiàn)登錄圖片驗(yàn)證碼功能
這篇文章主要給大家介紹一下如何SpringBoot+vue實(shí)現(xiàn)登錄圖片驗(yàn)證碼功能,文中有詳細(xì)的代碼示例,具有一定的參考價值,需要的朋友可以參考下2023-07-07Java多線程編程之ThreadLocal線程范圍內(nèi)的共享變量
這篇文章主要介紹了Java多線程編程之ThreadLocal線程范圍內(nèi)的共享變量,本文講解了ThreadLocal的作用和目的、ThreadLocal的應(yīng)用場景、ThreadLocal的使用實(shí)例等,需要的朋友可以參考下2015-05-05SpringBoot實(shí)現(xiàn)前后端、json數(shù)據(jù)交互以及Controller接收參數(shù)的幾種常用方式
這篇文章主要給大家介紹了關(guān)于SpringBoot實(shí)現(xiàn)前后端、json數(shù)據(jù)交互以及Controller接收參數(shù)的幾種常用方式,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2022-03-03