亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot使用異步線(xiàn)程池實(shí)現(xiàn)生產(chǎn)環(huán)境批量數(shù)據(jù)推送

 更新時(shí)間:2022年02月04日 11:23:24   作者:福隆苑居士  
本文主要介紹了SpringBoot使用異步線(xiàn)程池實(shí)現(xiàn)生產(chǎn)環(huán)境批量數(shù)據(jù)推送,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

SpringBoot使用異步線(xiàn)程池:

1、編寫(xiě)線(xiàn)程池配置類(lèi),自定義一個(gè)線(xiàn)程池;

2、定義一個(gè)異步服務(wù);

3、使用@Async注解指向定義的線(xiàn)程池;

這里以我工作中使用過(guò)的一個(gè)案例來(lái)做描述,我所在公司是醫(yī)療行業(yè),敏感數(shù)據(jù)需要上報(bào)到某監(jiān)管平臺(tái),所以有一個(gè)定時(shí)任務(wù)在流量較小時(shí)(一般是凌晨后)執(zhí)行上報(bào)行為。但特殊時(shí)期會(huì)存在一定要在工作時(shí)間大批量上報(bào)數(shù)據(jù)的情況,且要求短時(shí)間內(nèi)就要完成,此時(shí)就考慮寫(xiě)一個(gè)專(zhuān)門(mén)的異步上報(bào)接口手動(dòng)執(zhí)行,利用線(xiàn)程池上報(bào),極大提高了速度。

編寫(xiě)線(xiàn)程池配置類(lèi)

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
?
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
?
/**
?* 類(lèi)名稱(chēng):ExecutorConfig
?* ********************************
?* <p>
?* 類(lèi)描述:線(xiàn)程池配置
?*
?* @author guoj
?* @date 2021-09-07 09:00
?*/
@Configuration
@EnableAsync
@Slf4j
public class ExecutorConfig {
? ? /**
? ? ?* 定義數(shù)據(jù)上報(bào)線(xiàn)程池
? ? ?* @return
? ? ?*/
? ? @Bean("dataCollectionExecutor")
? ? public Executor dataCollectionExecutor() {
?
? ? ? ? ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
?
? ? ? ? // 核心線(xiàn)程數(shù)量:當(dāng)前機(jī)器的核心數(shù)
? ? ? ? executor.setCorePoolSize(
? ? ? ? ? ? ? ? Runtime.getRuntime().availableProcessors());
?
? ? ? ? // 最大線(xiàn)程數(shù)
? ? ? ? executor.setMaxPoolSize(
? ? ? ? ? ? ? ? Runtime.getRuntime().availableProcessors() * 2);
?
? ? ? ? // 隊(duì)列大小
? ? ? ? executor.setQueueCapacity(Integer.MAX_VALUE);
?
? ? ? ? // 線(xiàn)程池中的線(xiàn)程名前綴
? ? ? ? executor.setThreadNamePrefix("sjsb-");
?
? ? ? ? // 拒絕策略:直接拒絕
? ? ? ? executor.setRejectedExecutionHandler(
? ? ? ? ? ? ? ? new ThreadPoolExecutor.AbortPolicy());
?
? ? ? ? // 執(zhí)行初始化
? ? ? ? executor.initialize();
?
? ? ? ? return executor;
? ? }
}

 PS:

1)、需要注意,這里一定要自己定義ThreadPoolTaskExecutor線(xiàn)程池,否則springboot的異步注解會(huì)執(zhí)行默認(rèn)線(xiàn)程池,存在線(xiàn)程阻塞導(dǎo)致CPU飆高及內(nèi)存溢出的風(fēng)險(xiǎn)。這一點(diǎn)可以參考阿里開(kāi)發(fā)手冊(cè),線(xiàn)程池定義這塊明確提到了這一點(diǎn);

2)、在@Bean注解中定義線(xiàn)程池名稱(chēng),后面異步注解會(huì)用到。

編寫(xiě)異步服務(wù)

/**
?* 異步方法的服務(wù), 不影響主程序運(yùn)行。
?*/
@Service
public class AsyncService {
?
? ? private final Logger log = LoggerFactory.getLogger(AsyncService.class);
?
? ? /**
? ? ?* 發(fā)送短信
? ? ?*/
? ? @Async("sendMsgExecutor")
? ? public void sendMsg(String access_token, Consult item, Map<String, String> configMap) {
? ? ? ? // 此處編寫(xiě)發(fā)送短信業(yè)務(wù)
? ? ? ? // 1、buildConsultData();
? ? ? ? // 2、sendMsg();
? ? }
?
? ? /**
? ? ?* 發(fā)送微信訂閱消息
? ? ?*/
? ? @Async
? ? public void sendSubscribeMsg(String access_token, Consult item, Map<String, String> configMap) {
? ? ? ? // 此處編寫(xiě)發(fā)送微信訂閱消息業(yè)務(wù)
? ? ? ? // 1、buildConsultData();
? ? ? ? // 2、sendSubscribeMsg();
? ? }
?
? ? /**
? ? ?* 數(shù)據(jù)并上報(bào)
? ? ?*/
? ? @Async("dataCollectionExecutor")
? ? public void buildAndPostData(String access_token, Consult item, Map<String, String> configMap) {
? ? ? ? // 此處編寫(xiě)上報(bào)業(yè)務(wù),如拼接數(shù)據(jù),然后執(zhí)行上報(bào)。
? ? ? ? // 1、buildConsultData();
? ? ? ? // 2、postData();
? ? }
}

PS:
1)、以上是代碼片段,個(gè)人經(jīng)驗(yàn)認(rèn)為專(zhuān)門(mén)定義一個(gè)異步service存放各個(gè)異步方法最佳,這樣可以避免編碼時(shí)一些誤操作比如異步方法不是void或者是private修飾,導(dǎo)致@Async注解失效的情況,同時(shí)可以安排每個(gè)注解指向不同的自定義線(xiàn)程池更加靈活;
2)、@Async注解中的名稱(chēng)就是上面定義的自定義線(xiàn)程池名稱(chēng),這樣業(yè)務(wù)執(zhí)行時(shí)就會(huì)從指定線(xiàn)程池中獲取異步線(xiàn)程。

異步批量上報(bào)數(shù)據(jù)

@Autowired
private AsyncService asyncService;
?
/**
?* 手動(dòng)上報(bào)問(wèn)診記錄,線(xiàn)程池方式。
?*/
public void manualUploadConsultRecordsAsync(String channel, Date startTime, Date endTime) {
?
? ? // 查詢(xún)指定時(shí)間內(nèi)的問(wèn)診記錄
? ?List<Consult> consultList = consultService
? ? ? ?.findPaidListByChannelAndTime(channel, startTime, endTime, configMap.get("serviceId"));
?
? ?if (!CollectionUtils.isEmpty(consultList)) {
?
? ? ? ?log.debug("[SendWZDataService][manualUploadConsultRecordsAsync]>>>> 手動(dòng)上報(bào)問(wèn)診記錄, 一共[{}]條", consultList.size());
?
? ? ? ?consultList.forEach((item) -> {
? ? ? ? ? ?try {
? ? ? ? ? ? ? ?// 異步調(diào)用,使用線(xiàn)程池。
? ? ? ? ? ? ? ?asyncService.buildAndPostData(access_token, item, configMap);
? ? ? ? ? ?} catch (Exception ex) {
? ? ? ? ? ? ? ?log.error("[SendWZDataService][manualUploadConsultRecordsAsync]>>>> 手動(dòng)上報(bào)問(wèn)診記錄發(fā)生異常: ", ex);
? ? ? ? ? ?}
? ? ? ?});
? ?}
}

總結(jié)

以上方式已經(jīng)在生產(chǎn)環(huán)境運(yùn)行,在工作時(shí)間內(nèi)執(zhí)行過(guò)很多次,一次數(shù)萬(wàn)條記錄基本是幾分鐘內(nèi)就全部上報(bào)完畢,而正常循環(huán)遍歷時(shí)一次大概需要半個(gè)小時(shí)左右。

線(xiàn)程池的使用方式往往來(lái)源于業(yè)務(wù)場(chǎng)景,如果類(lèi)似的業(yè)務(wù)不存在緊急處理的情況,大體還是以任務(wù)調(diào)度執(zhí)行為主,因?yàn)楦踩?。如果存在緊急處理的情況,那么使用SpringBoot+線(xiàn)程池的方式不僅能節(jié)省非常多的時(shí)間,且不占用主線(xiàn)程的執(zhí)行空間。

到此這篇關(guān)于SpringBoot使用異步線(xiàn)程池實(shí)現(xiàn)生產(chǎn)環(huán)境批量數(shù)據(jù)推送的文章就介紹到這了,更多相關(guān)SpringBoot 生產(chǎn)環(huán)境批量數(shù)據(jù)推送內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于servlet的執(zhí)行原理與生命周期(全面解析)

    基于servlet的執(zhí)行原理與生命周期(全面解析)

    下面小編就為大家分享一篇servlet的執(zhí)行原理與生命周期全面解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • 基于ReentrantLock的實(shí)現(xiàn)原理講解

    基于ReentrantLock的實(shí)現(xiàn)原理講解

    這篇文章主要介紹了ReentrantLock的實(shí)現(xiàn)原理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java的代理模式你真的了解嗎

    Java的代理模式你真的了解嗎

    這篇文章主要為大家詳細(xì)介紹了Java的代理模式,結(jié)構(gòu)型模式主要總結(jié)了一些類(lèi)或?qū)ο蠼M合在一起的經(jīng)典結(jié)構(gòu),這些經(jīng)典的結(jié)構(gòu)可以解決特定應(yīng)用場(chǎng)景的問(wèn)題,包括:代理模式、橋接模式、裝飾器模式、適配器模式、門(mén)面模式、組合模式、享元模式
    2022-03-03
  • 使用jdk1.8實(shí)現(xiàn)將list根據(jù)指定的值去分組的操作

    使用jdk1.8實(shí)現(xiàn)將list根據(jù)指定的值去分組的操作

    這篇文章主要介紹了使用jdk1.8實(shí)現(xiàn)將list根據(jù)指定的值去分組的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • Java實(shí)現(xiàn)在線(xiàn)編輯預(yù)覽office文檔詳解

    Java實(shí)現(xiàn)在線(xiàn)編輯預(yù)覽office文檔詳解

    PageOffice是一款在線(xiàn)的office編輯軟件,幫助Web應(yīng)用系統(tǒng)或Web網(wǎng)站實(shí)現(xiàn)用戶(hù)在線(xiàn)編輯Word、Excel、PowerPoint文檔,下面我們就來(lái)看看如何使用Java實(shí)現(xiàn)在線(xiàn)預(yù)覽office吧
    2024-01-01
  • Java并發(fā)容器介紹

    Java并發(fā)容器介紹

    這篇文章主要介紹了Java并發(fā)容器,Java并發(fā)包(concurrent)是Java用來(lái)處理并發(fā)問(wèn)題的利器,該并發(fā)包中主要有原子類(lèi),鎖(lock),并發(fā)容器類(lèi)等等。本系列博客主要就是介紹并發(fā)包中一些常用的并發(fā)容器,常用的類(lèi),那么我們就來(lái)看看下面文章的詳細(xì)內(nèi)容吧
    2021-10-10
  • Java中Future接口詳解

    Java中Future接口詳解

    這篇文章主要介紹了Java中Future接口詳解,本文通過(guò)案例給大家詳細(xì)講解了Java中Future接口,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • java中實(shí)現(xiàn)自定義注解方式

    java中實(shí)現(xiàn)自定義注解方式

    注解是Java中的一種元數(shù)據(jù),可以修飾方法、類(lèi)、參數(shù)和包等,自定義注解需要public修飾符、@interface關(guān)鍵字,以及注解名稱(chēng)和類(lèi)型元素,元注解如@Target、@Retention等用于修飾注解,指定注解的適用范圍和生命周期,自定義注解的使用涉及到通過(guò)反射解析注解
    2024-11-11
  • 一文徹底吃透SpringMVC中的轉(zhuǎn)發(fā)和重定向

    一文徹底吃透SpringMVC中的轉(zhuǎn)發(fā)和重定向

    大家應(yīng)該都知道springmvc本來(lái)就會(huì)把返回的字符串作為視圖名解析,然后轉(zhuǎn)發(fā)到對(duì)應(yīng)的視圖,這篇文章主要給大家介紹了關(guān)于SpringMVC中轉(zhuǎn)發(fā)和重定向的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • Java 不使用第三方變量交換兩個(gè)變量值的四種方法詳解

    Java 不使用第三方變量交換兩個(gè)變量值的四種方法詳解

    這篇文章主要介紹了四種不使用第三方變量交換兩個(gè)變量值的方法。文中對(duì)于四種方法進(jìn)行了詳細(xì)的分析,需要的小伙伴們可以跟隨小編一起學(xué)習(xí)一下
    2021-12-12

最新評(píng)論