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

