SpringBoot非同步呼叫方法實現場景程式碼例項
阿新 • • 發佈:2020-04-09
一、背景
專案中肯定會遇到非同步呼叫其他方法的場景,比如有個計算過程,需要計算很多個指標的值,但是每個指標計算的效率快慢不同,如果採用同步執行的方式,執行這一個過程的時間是計算所有指標的時間之和。比如:
方法A:計算指標x,指標y,指標z的值,其中計算指標x需要1s,計算指標y需要2s,指標z需要3s。最終執行完方法A就是5s。
現在用非同步的方式優化一下
方法A非同步呼叫方法B,方法C,方法D,方法B,方法C,方法D分別計算指標x,指標y,指標z的值,那麼最終執行完方法A的時間則是3s。
還有一種用途是當一個業務裡面需要多個請求時,這時候非同步併發請求所得到的回報遠遠是物有所值的。因為他是非同步執行的,話不多說,一下是在springBoot裡面使用併發請求;
二、spring boot中非同步併發使用
2.1、appllication.yml
#****************整合Async執行緒池開始******************* async: # Async執行緒池 配置 executor: corepoolsize: 20 maxpoolsize: 25 queuecapacity: 40 keepaliveseconds: 200 threadnameprefix: appasync awaitterminationseconds: 60 #*****************整合Async執行緒池結束******************
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(); // 基礎執行緒數 corePoolSize: 10 executor.setCorePoolSize(corePoolSize); // 最大執行緒數 maxPoolSize: 15 executor.setMaxPoolSize(maxPoolSize); // 佇列長度 queueCapacity: 25 executor.setQueueCapacity(queueCapacity); // 執行緒池維護執行緒所允許的空閒時間,單位為秒 keepAliveSeconds: 200 executor.setKeepAliveSeconds(keepAliveSeconds); // 執行緒名字 threadNamePrefix: appasync executor.setThreadNamePrefix(threadNamePrefix); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待所有任務都完成再繼續銷燬其他的Bean executor.setWaitForTasksToCompleteOnShutdown(true); // 執行緒池中任務的等待時間,如果超過這個時候還沒有銷燬就強制銷燬,以確保應用最後能夠被關閉,而不是阻塞住 executor.setAwaitTerminationSeconds(awaitTerminationSeconds); executor.initialize(); return executor; } }
2.3、執行緒池監控(這個可有可無,主要是為了對執行緒池引數及時的調優)
@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(); // 當前排隊執行緒數 int queueSize = executor.getQueue().size(); // 當前活動執行緒數 int activeCount = executor.getActiveCount(); // 執行完執行緒數 long completedThreadCount = executor.getCompletedTaskCount(); // 匯流排程數 long taskCount = executor.getTaskCount(); // 初始執行緒數 int poolSize = executor.getPoolSize(); // 核心執行緒數 int corePoolSize = executor.getCorePoolSize(); // 執行緒池是否終止 boolean isTerminated = executor.isTerminated(); // 線城池是否關閉 boolean isShutdown = executor.isShutdown(); // 執行緒空閒時間 long keepAliveTime = executor.getKeepAliveTime(TimeUnit.MILLISECONDS); // 最大允許執行緒數 long maximumPoolSize = executor.getMaximumPoolSize(); // 執行緒池中存在的最大執行緒數 long largestPoolSize = executor.getLargestPoolSize(); Map<String,Object> threadPoolData = new HashMap<>(18); threadPoolData.put("當前排隊執行緒數",queueSize); threadPoolData.put("當前活動執行緒數",activeCount); threadPoolData.put("執行完執行緒數",completedThreadCount); threadPoolData.put("匯流排程數",taskCount); threadPoolData.put("初始執行緒數",poolSize); threadPoolData.put("核心執行緒數",corePoolSize); threadPoolData.put("執行緒池是否終止",isTerminated); threadPoolData.put("線城池是否關閉",isShutdown); threadPoolData.put("執行緒空閒時間",keepAliveTime); threadPoolData.put("最大允許執行緒數",maximumPoolSize); threadPoolData.put("執行緒池中存在的最大執行緒數",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(){ /** * 先將耗時的、相互之間無依賴的操作先執行,由於其執行結果暫時不是特別關注,所以 */ Future<String> futureA = functionA(); Future<String> futureB = functionB(); /** * 執行其他的操作,其實functionA(),functionB()也在工作 */ aaa(); /** * 獲取非同步的結果,然後計算 */ 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("我是"); }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。