国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

@Async異步線程:Spring 自帶的異步解決方案

這篇具有很好參考價(jià)值的文章主要介紹了@Async異步線程:Spring 自帶的異步解決方案。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

@Async異步線程:Spring 自帶的異步解決方案

前言?

? ? ? ? 在項(xiàng)目應(yīng)用中,使用MQ異步調(diào)用來(lái)實(shí)現(xiàn)系統(tǒng)性能優(yōu)化,完成服務(wù)間數(shù)據(jù)同步是常用的技術(shù)手段。如果是在同一臺(tái)服務(wù)器內(nèi)部,不涉及到分布式系統(tǒng),單純的想實(shí)現(xiàn)部分業(yè)務(wù)的異步執(zhí)行,這里介紹一個(gè)更簡(jiǎn)單的異步方法調(diào)用。

????????對(duì)于異步方法調(diào)用,從Spring3 開(kāi)始提供了@Async 注解,該注解可以被標(biāo)注在方法上,以便異步地調(diào)用該方法。調(diào)用者將在調(diào)用時(shí)立即返回,而方法的實(shí)際執(zhí)行將提交給 Spring TaskExecutor 的任務(wù)中,由指定的線程池中的線程執(zhí)行。

????????本文講述了@Async注解在Spring體系中的簡(jiǎn)單應(yīng)用,僅供學(xué)習(xí),歡迎意見(jiàn)反饋。??


正文

一、Spring線程池的分類(lèi)

????????以下是官方已經(jīng)實(shí)現(xiàn)的常見(jiàn)的5個(gè)TaskExecuter。Spring 宣稱(chēng)對(duì)于任何場(chǎng)景,這些TaskExecuter完全夠用了:

線程 特點(diǎn)
SimpleAsyncTaskExecutor 每次請(qǐng)求新開(kāi)線程,沒(méi)有最大線程數(shù)設(shè)置.不是真的線程池,這個(gè)類(lèi)不重用線程,每次調(diào)用都會(huì)創(chuàng)建一個(gè)新的線程
SyncTaskExecutor 不是異步的線程。同步可以用SyncTaskExecutor,但這個(gè)可以說(shuō)不算一個(gè)線程池,因?yàn)檫€在原線程執(zhí)行。這個(gè)類(lèi)沒(méi)有實(shí)現(xiàn)異步調(diào)用,只是一個(gè)同步操作。
ConcurrentTaskExecutor Executor的適配類(lèi),不推薦使用。如果ThreadPoolTaskExecutor不滿(mǎn)足要求時(shí),才用考慮使用這個(gè)類(lèi)。
SimpleThreadPoolTaskExecutor 是Quartz的SimpleThreadPool的類(lèi)。線程池同時(shí)被quartz和非quartz使用,才需要使用此類(lèi)。
ThreadPoolTaskExecutor 最常使用,推薦,是阿里巴巴Java開(kāi)發(fā)規(guī)范中指定的線程類(lèi),要求jdk版本大于等于5。其實(shí)質(zhì)是對(duì)java.util.concurrent.ThreadPoolExecutor 的包裝。

???????參考阿里巴巴java開(kāi)發(fā)規(guī)范,?在線程池應(yīng)用中:線程池不允許使用Executors去創(chuàng)建,也不允許使用系統(tǒng)默認(rèn)的線程池,推薦通過(guò) ThreadPoolExecutor 的方式,這樣的處理方式讓開(kāi)發(fā)的工程師更加明確線程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。

二、SpringBoot中使用@Async

? ? ? ? 使用異步線程調(diào)用方法,過(guò)程如下:

  • 編寫(xiě)配置類(lèi),定義線程池
  • 啟動(dòng)類(lèi)/配置文件上加上注解:@EnableAsync
  • 方法上加上注解:@Async

? ? ? ? 下面演示案例中,我本地項(xiàng)目的目錄,僅供參考:

@Async異步線程:Spring 自帶的異步解決方案

2.1 啟用@Async

? ? ? ? 關(guān)鍵注解?@EnableAsync ?。?!可以加載啟動(dòng)類(lèi)上,也可以加在配置文件上,效果是一樣的。

  • ?方式一:基于Springboot啟動(dòng)類(lèi)啟用
@EnableAsync
@SpringBootApplication
public class AsyncApplication {

    public static void main(String[] args) {
        SpringApplication.run(AsyncApplication.class, args);
    }

}
  • 方式二:基于Java配置的啟用
// com.example.async.service 為即將開(kāi)啟異步線程業(yè)務(wù)的包位置(后面有詳細(xì)講解)
@EnableAsync
@Configuration
@ComponentScan("com.example.async.service")
public class AsyncConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        return executor();
    }
    ...
}

2.2 @Async與線程池

????????Spring應(yīng)用默認(rèn)的線程池,指在@Async注解在使用時(shí),不指定線程池的名稱(chēng)。查看源碼,@Async的默認(rèn)線程池為SimpleAsyncTaskExecutor

@Slf4j
@Service
public class BusinessServiceImpl implements BusinessService {

    /**
     * 方法4:沒(méi)有指定線程池,驗(yàn)證默認(rèn)線程池也ok(不推薦:規(guī)避資源耗盡的風(fēng)險(xiǎn))
     */
    @Async
    public void asyncDemo4() {
        log.info("asyncDemo4:" + Thread.currentThread().getName() + " 正在執(zhí)行 ----------");
        try {
            Thread.sleep(2*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("asyncDemo4:" + Thread.currentThread().getName() + " 執(zhí)行結(jié)束?。?);
    }
}

2.3 @Async自定義線程池

????????自定義線程池,可對(duì)系統(tǒng)中線程池更加細(xì)粒度的控制,方便調(diào)整線程池大小配置,線程執(zhí)行異??刂坪吞幚?。在設(shè)置系統(tǒng)自定義線程池代替默認(rèn)線程池時(shí),雖可通過(guò)多種模式設(shè)置,但替換默認(rèn)線程池最終產(chǎn)生的線程池有且只能設(shè)置一個(gè)(不能設(shè)置多個(gè)類(lèi)繼承AsyncConfigurer)。

????????自定義線程池有如下模式:

  1. 重新實(shí)現(xiàn)接口AsyncConfigurer;
  2. 繼承AsyncConfigurerSupport;
  3. 配置由自定義的TaskExecutor替代內(nèi)置的任務(wù)執(zhí)行器;

? ? ? ? 三者使用方式大體相同,下面的案例將展示說(shuō)明其一:實(shí)現(xiàn)接口AsyncConfigurer接口的方式。

  • 配置一個(gè)線程池?ThreadPoolTaskExecutor
/**
 * com.example.async.service:即將開(kāi)啟異步線程的業(yè)務(wù)方法是哪個(gè)
 *
 * 解釋?zhuān)? *  1.即將開(kāi)啟異步線程業(yè)務(wù)的包位置:com.example.async.service
 *  2.通過(guò) ThreadPoolExecutor 的方式,規(guī)避資源耗盡的風(fēng)險(xiǎn)
 */
@EnableAsync
@Configuration
@ComponentScan("com.example.async.service")
public class AsyncConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        return executor();
    }

    /**
     * 執(zhí)行需要依賴(lài)線程池,這里就來(lái)配置一個(gè)線程池
     * 1.當(dāng)池子大小小于corePoolSize,就新建線程,并處理請(qǐng)求
     * 2.當(dāng)池子大小等于corePoolSize,把請(qǐng)求放入workQueue(QueueCapacity)中,池子里的空閑線程就去workQueue中取任務(wù)并處理
     * 3.當(dāng)workQueue放不下任務(wù)時(shí),就新建線程入池,并處理請(qǐng)求,如果池子大小撐到了maximumPoolSize,就用RejectedExecutionHandler來(lái)做拒絕處理
     * 4.當(dāng)池子的線程數(shù)大于corePoolSize時(shí),多余的線程會(huì)等待keepAliveTime長(zhǎng)時(shí)間,如果無(wú)請(qǐng)求可處理就自行銷(xiāo)毀
     */
    @Bean("asyncExecutor")
    public ThreadPoolTaskExecutor executor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //設(shè)置線程名
        executor.setThreadNamePrefix("async-method-execute-");
        //設(shè)置核心線程數(shù)
        executor.setCorePoolSize(10);
        //設(shè)置最大線程數(shù)
        executor.setMaxPoolSize(50);
        //線程池所使用的緩沖隊(duì)列
        executor.setQueueCapacity(100);
        //設(shè)置多余線程等待的時(shí)間,單位:秒
        executor.setKeepAliveSeconds(10);
        // 初始化線程
        executor.initialize();
        return executor;
    }
}
  • 執(zhí)行異步線程方法,指定線程池:value 要與配置類(lèi)?Bean() 中的name相同?
/**
 * 異步線程 - 執(zhí)行業(yè)務(wù)
 * 注意:
 *  1.@Async 注解調(diào)用用線程池,不指定的話默認(rèn):SimpleAsyncTaskExecutor
 *  2.SimpleAsyncTaskExecutor 不是真的線程池,這個(gè)類(lèi)不重用線程,默認(rèn)每次調(diào)用都會(huì)創(chuàng)建一個(gè)新的線程
 */
@Slf4j
@Service
public class AsyncServiceImpl implements AsyncService {
    /**
     * 方法1:@Async 標(biāo)注為異步任務(wù):執(zhí)行此方法的時(shí)候,會(huì)單獨(dú)開(kāi)啟線程來(lái)執(zhí)行,不影響主線程的執(zhí)行
     */
    @Async("asyncExecutor")
    public void asyncDemo1() {
        log.info("asyncDemo1:" + Thread.currentThread().getName() + " 正在執(zhí)行 ----------");
        // 故意等10秒,那么異步線程開(kāi)起來(lái),這樣明顯看到:方法2不用等方法1執(zhí)行完就調(diào)用了
        try {
            Thread.sleep(10*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("asyncDemo1:" + Thread.currentThread().getName() + " 執(zhí)行結(jié)束??!");
    }

    /**
     * 方法2:與方法1一起執(zhí)行,證明2個(gè)線程異步執(zhí)行,互不干擾
     */
    @Async("asyncExecutor")
    public void asyncDemo2() {
        log.info("asyncDemo2:" + Thread.currentThread().getName() + " 正在執(zhí)行 ----------");
        try {
            Thread.sleep(5*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("asyncDemo2:" + Thread.currentThread().getName() + " 執(zhí)行結(jié)束??!");
    }

    /**
     * 方法3:沒(méi)有指定線程池,驗(yàn)證默認(rèn)線程池也ok(不推薦:規(guī)避資源耗盡的風(fēng)險(xiǎn))
     */
    @Async
    public void asyncDemo3() {
        log.info("asyncDemo3:" + Thread.currentThread().getName() + " 正在執(zhí)行 ----------");
        try {
            Thread.sleep(1*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("asyncDemo3:" + Thread.currentThread().getName() + " 執(zhí)行結(jié)束?。?);
    }
}

2.4 啟動(dòng)測(cè)試

? ? ? ? 通過(guò) AsyncApplication 啟動(dòng) SpringBoot 項(xiàng)目,Postman 進(jìn)行接口測(cè)試:

http://127.0.0.1:8080/async/demo

  • 我寫(xiě)了4個(gè)demo,分別模擬4種情況,詳情在注釋里有寫(xiě)。
@Slf4j
@RestController
@RequestMapping("/async")
public class AsyncControllor {

    @Autowired
    private AsyncService asyncMethodService;
    @Autowired
    private BusinessService businessService;

    @GetMapping("/demo")
    public String demo()  {
        log.info("接口調(diào)用:【開(kāi)始】 --------------------");
        try {
            // 執(zhí)行異步任務(wù) - 自定義線程池
            asyncMethodService.asyncDemo1();
            asyncMethodService.asyncDemo2();
            asyncMethodService.asyncDemo3();
            // 執(zhí)行異步任務(wù) - 默認(rèn)線程池
            businessService.asyncDemo4();
        } catch (Exception e) {
            return "Exception";
        }
        log.info("接口調(diào)用:【結(jié)束】 --------------------");
        return "success";
    }
}
  • 運(yùn)行結(jié)果:接口執(zhí)行結(jié)束,異步線程仍在運(yùn)行

@Async異步線程:Spring 自帶的異步解決方案文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-423536.html


總結(jié)

  1. @EnableAsync 是啟動(dòng) @Async 異步線程的關(guān)鍵,可以加載啟動(dòng)類(lèi)上,也可以加在配置文件上;
  2. 為了規(guī)避資源耗盡的風(fēng)險(xiǎn),推薦通過(guò) ThreadPoolExecutor 的方式創(chuàng)建線程池;
  3. @Async 注解標(biāo)注在方法上,以便異步地調(diào)用該方法;

到了這里,關(guān)于@Async異步線程:Spring 自帶的異步解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【前端面經(jīng)】JS-異步解決方案

    同步和異步 眾所周知, JavaScript 是一門(mén)單線程的語(yǔ)言, 單線程就意味著同一時(shí)間只能執(zhí)行一個(gè)任務(wù), 當(dāng)前任務(wù)執(zhí)行結(jié)束, 才會(huì)執(zhí)行下一個(gè)任務(wù). 這種模式的好處就是執(zhí)行環(huán)境比較單純, 但壞處也很明顯, 一旦有某個(gè)任務(wù)卡住了, 就會(huì)導(dǎo)致整個(gè)程序阻塞. 為了解決這個(gè)問(wèn)題, JS將任務(wù)的

    2024年02月02日
    瀏覽(30)
  • JS for循環(huán)異步解決方案

    JavaScript中的for循環(huán)是一種同步操作,它將阻塞代碼的執(zhí)行,直到循環(huán)完成。但是,在處理異步操作時(shí),使用同步for循環(huán)會(huì)導(dǎo)致問(wèn)題。 為了解決這個(gè)問(wèn)題,可以使用以下兩種異步解決方案: 遞歸是一種有效的解決方案,它可以確保異步操作按照預(yù)期執(zhí)行。以下是使用遞歸實(shí)現(xiàn)

    2024年02月13日
    瀏覽(40)
  • Go異步任務(wù)解決方案 Asynq

    Go異步任務(wù)解決方案 Asynq

    今天為大家介紹一個(gè)Go處理異步任務(wù)的解決方案:Asynq,是一個(gè) Go 庫(kù),用于排隊(duì)任務(wù)并與 worker 異步處理它們。它由Redis提供支持,旨在實(shí)現(xiàn)可擴(kuò)展且易于上手。 Asynq 是一個(gè) Go 庫(kù),用于對(duì)任務(wù)進(jìn)行排隊(duì)并與工作人員異步處理它們。 Asynq 工作原理的高級(jí)概述: 客戶(hù)端將任務(wù)放入

    2024年01月17日
    瀏覽(18)
  • 筆記本外接鍵盤(pán)解決方案:禁用筆記本自帶鍵盤(pán)

    筆記本外接鍵盤(pán)時(shí),有時(shí)會(huì)將外接鍵盤(pán)放置在筆記本自帶鍵盤(pán)上,加上現(xiàn)代筆記本設(shè)計(jì)輕薄,外接鍵盤(pán)(尤其是108鍵的)在使用過(guò)程中經(jīng)常觸碰自帶鍵盤(pán),禁用自帶鍵盤(pán)后將提供極大的工作便利。 通過(guò)系統(tǒng)自帶sc命令禁用PS/2(i8042prt)服務(wù): 禁用服務(wù): 恢復(fù)服務(wù): I8042prt是

    2024年02月12日
    瀏覽(98)
  • 【go】異步任務(wù)解決方案Asynq實(shí)戰(zhàn)

    Asynq 是一個(gè) Go 庫(kù),一個(gè)高效的分布式任務(wù)隊(duì)列。 Asynq 工作原理: 客戶(hù)端(生產(chǎn)者)將任務(wù)放入隊(duì)列 服務(wù)器(消費(fèi)者)從隊(duì)列中拉出任務(wù)并為每個(gè)任務(wù)啟動(dòng)一個(gè)工作 goroutine 多個(gè)工作人員同時(shí)處理任務(wù) git庫(kù):https://github.com/hibiken/asynq Asynq 使用 Redis 作為消息代理。client 和 se

    2024年02月10日
    瀏覽(20)
  • 詳解JS的四種異步解決方案!

    詳解JS的四種異步解決方案!

    目錄 同步異步的概念 js中異步的應(yīng)用場(chǎng)景 實(shí)現(xiàn)異步的四種方法 1、 回調(diào)函數(shù) 2、Promise 3、Generator 4、 async/await ????????「異步編程」 是前端工程師日常開(kāi)發(fā)中經(jīng)常會(huì)用到的技術(shù),也是校招面試過(guò)程中常考的一個(gè)知識(shí)點(diǎn)。 ????????通過(guò)掌握 「異步編程」 的四種方式,可

    2024年01月18日
    瀏覽(43)
  • JavaScript 異步解決方案 Promise 全解析(轉(zhuǎn)載)

    Promise 是一個(gè) JS 的異步編程解決方案,解決了傳統(tǒng)異步編程回調(diào)地獄的問(wèn)題。 從語(yǔ)義上來(lái)說(shuō): Promise 是一個(gè)向外部傳達(dá)異步編程操作消息的對(duì)象。 JS里一個(gè)promise可以有以下幾種基本狀態(tài): nothing happened yet \\\"locked in\\\" to another promise fulfilled rejected 其中{1,2}為 pending ,{3,4}為 settl

    2024年02月08日
    瀏覽(25)
  • 【多線程】| 線程沖突解決方案

    【多線程】| 線程沖突解決方案

    同一進(jìn)程內(nèi)的線程是共享同一內(nèi)存空間的,所以在多個(gè)線程的進(jìn)程里,線程是可以同時(shí)操作這個(gè)進(jìn)程空間的數(shù)據(jù)的,這樣就容易造成線程沖突的情況。 舉個(gè)小李子:一個(gè)房子里(代表一個(gè)進(jìn)程),只有一個(gè)廁所(代表一個(gè)資源)。屋子里面有兩個(gè)人A和B(代表兩個(gè)線程),共

    2024年02月05日
    瀏覽(92)
  • 實(shí)現(xiàn)不同局域網(wǎng)文件共享的解決方案:使用Python自帶HTTP服務(wù)和端口映射

    實(shí)現(xiàn)不同局域網(wǎng)文件共享的解決方案:使用Python自帶HTTP服務(wù)和端口映射

    數(shù)據(jù)共享作為和連接作為互聯(lián)網(wǎng)的基礎(chǔ)應(yīng)用,不僅在商業(yè)和辦公場(chǎng)景有廣泛的應(yīng)用,對(duì)于個(gè)人用戶(hù)也有很強(qiáng)的實(shí)用意義。也正因如此,大量數(shù)據(jù)共享軟件被開(kāi)發(fā)出來(lái),云存儲(chǔ)的概念也被重復(fù)炒作。對(duì)于愛(ài)好折騰的筆者來(lái)說(shuō),用最簡(jiǎn)單的工具找尋私人共享和存儲(chǔ)解決方案,也是

    2024年02月11日
    瀏覽(17)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包