欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java SpringMVC異步處理詳解

 更新時(shí)間:2021年10月26日 15:17:07   作者:路人甲Java  
這篇文章主要介紹了Java springmvc的處理異步,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

1、本篇內(nèi)容

本文讓大家掌握 springmvc 中異步處理請(qǐng)求,特別牛逼的一個(gè)功能,大家一定要掌握。

2、看段代碼,分析問(wèn)題

@ResponseBody
@RequestMapping("/async/m1.do")
public String m1() throws InterruptedException {
    long st = System.currentTimeMillis();
    System.out.println("主線程:" + Thread.currentThread() + "," + st + ",開始");
    //休眠3秒,模擬耗時(shí)的業(yè)務(wù)操作
    TimeUnit.SECONDS.sleep(3);
    long et = System.currentTimeMillis();
    System.out.println("主線程:" + Thread.currentThread() + "," + st + ",結(jié)束,耗時(shí)(ms):" + (et - st));
    return "ok";
}

這段代碼很簡(jiǎn)單

這段代碼是 springmvc 提供的一個(gè)接口

內(nèi)部休眠了 3 秒鐘,用來(lái)模擬耗時(shí)的操作

方法內(nèi)部有 2 條日志(日志中包含了當(dāng)前線程、開始時(shí)間、結(jié)束時(shí)間、耗時(shí))

瀏覽器中訪問(wèn)下這個(gè)接口,效果如下,可以看到接口耗時(shí) 3s 左右。

控制臺(tái)輸出

主線程:Thread[http-nio-8080-exec-1,5,main],1624889293055,開始
主線程:Thread[http-nio-8080-exec-1,5,main],1624889293055,結(jié)束,耗時(shí)(ms):3002

從輸出中,我們可以看出,這個(gè)接口從開始到結(jié)束都是由 tomcat 中的線程來(lái)處理用戶請(qǐng)求的,也就是說(shuō),3 秒這段時(shí)間內(nèi),tomcat 中的一個(gè)線程會(huì)被當(dāng)前請(qǐng)求一直占用了則,tomcat 線程是有最大值的,默認(rèn)情況下好像是 75,那么問(wèn)題來(lái)了。

當(dāng) 3 秒之內(nèi),來(lái)的請(qǐng)求數(shù)量超過(guò)了 tomcat 最大線程數(shù)的時(shí)候,其他請(qǐng)求就無(wú)法處理了,而此時(shí) tomcat 中這些線程都處理 sleep 3s 的休眠狀態(tài),cpu 此時(shí)沒(méi)活干,此時(shí)就會(huì)造成機(jī)器沒(méi)活干,但是呢又不能處理新的請(qǐng)求,這就是坑啊,浪費(fèi)資源,怎么辦呢?

遇到這種場(chǎng)景的,也就是說(shuō)接口內(nèi)部比價(jià)耗時(shí),但是又不能充分利用 cpu 的,我們可以采用異步的方式來(lái)處理請(qǐng)求,過(guò)程如下:

tomcat 線程,將請(qǐng)求轉(zhuǎn)發(fā)給我們自定義的子線程去處理這個(gè)請(qǐng)求,然后 tomcat 就可以繼續(xù)去接受新的請(qǐng)求了。

3、springmvc 中異步處理

主要有 3 個(gè)大的步驟。

step1:servlet 開啟異步處理支持

web.xml 中開啟 servlet 異步支持

step2:Filter 中添加異步支持

如果我們的異步請(qǐng)求需要經(jīng)過(guò) Filter 的,那么需要在 web.xml 對(duì)這個(gè) Filter 添加異步支持.

step3:接口返回值為 DeferredResult

這個(gè)步驟中細(xì)節(jié)比較多,當(dāng)需要異步響應(yīng)請(qǐng)求的時(shí)候,返回值需要為 DeferredResult,具體參考下面案例代碼,詳細(xì)信息都在注釋中了,大家注意看注釋。

第 1 步:創(chuàng)建 DeferredResult<返回值類型>(超時(shí)時(shí)間[毫秒],超時(shí)回調(diào)的代碼)

第 2 步:在子線程中異步處理業(yè)務(wù),調(diào)用 DeferredResult 的 setResult 方法,設(shè)置最終返回到客戶端的結(jié)果,此方法調(diào)用以后,客戶端將接收到返回值,然后響應(yīng)過(guò)程請(qǐng)求就結(jié)束了

第 3 步:將 DefaultResult 作為方法返回值

/**
 * 使用springmvc的異步功能,業(yè)務(wù)處理放在異步線程中執(zhí)行
 *
 * @param timeout 異步處理超時(shí)時(shí)間(毫秒)
 * @return
 */
@ResponseBody
@RequestMapping("/async/m2/{timeout}.do")
public DeferredResult m2(@PathVariable("timeout") long timeout) {
    long st = System.currentTimeMillis();
    System.out.println("主線程:" + Thread.currentThread() + "," + st + ",開始");
    /**
     * 1、創(chuàng)建DeferredResult<返回值類型>(超時(shí)時(shí)間[毫秒],超時(shí)回調(diào)的代碼)
     */
    DeferredResult result = new DeferredResult(timeout, () -> {
        System.out.println("超時(shí)了");
        return "timeout";
    });
    //2、異步處理業(yè)務(wù),
    new Thread(() -> {
        //開啟一個(gè)異步線程,在異步線程中進(jìn)行業(yè)務(wù)處理操作
        try {
            TimeUnit.SECONDS.sleep(3);
            //3、調(diào)用DeferredResult的setResult方法,設(shè)置最終返回到客戶端的結(jié)果,此方法調(diào)用以后,客戶端將接收到返回值
            result.setResult("ok");
        } catch (InterruptedException e) {
            result.setResult("發(fā)生異常了:" + e.getMessage());
        }
    }).start();
    long et = System.currentTimeMillis();
    System.out.println("主線程:" + Thread.currentThread() + "," + st + ",結(jié)束,耗時(shí)(ms):" + (et - st));
    //3、將DefaultResult作為方法返回值
    return result;
}

上面的 m2 方法個(gè) timeout 參數(shù),調(diào)用者通過(guò)這個(gè)參數(shù)來(lái)指定接口的超時(shí)時(shí)間,未超時(shí)的情況下,也就是說(shuō) timeout 大于 3 秒的時(shí)候,此時(shí)會(huì)輸出 ok,否則將出現(xiàn)超時(shí),此時(shí)會(huì)將 DeferredResult 構(gòu)造器第 2 個(gè)參數(shù)的執(zhí)行結(jié)果作為最終的響應(yīng)結(jié)果,即會(huì)向客戶端輸出 timeout。

使用建議:案例開啟了一個(gè)新的子線程來(lái)執(zhí)行業(yè)務(wù)操作,生產(chǎn)環(huán)境中,建議大家采用線程池的方式,效率更高。

下面我們來(lái)通過(guò) 2 個(gè) case 來(lái)模擬下這個(gè)接口超時(shí)和正常的結(jié)果。

4、模擬非超時(shí)請(qǐng)求

當(dāng) timeout 大于 3 秒時(shí),才不會(huì)出現(xiàn)超時(shí),此時(shí)我們傳遞 4000 毫秒來(lái)試試

控制臺(tái)輸出如下,可以看到主線程瞬間就結(jié)束了。

主線程:Thread[http-nio-8080-exec-6,5,main],1624891886020,開始
主線程:Thread[http-nio-8080-exec-6,5,main],1624891886020,結(jié)束,耗時(shí)(ms):0

5、模擬超時(shí)請(qǐng)求

當(dāng) timeout 小于 3 秒會(huì)出現(xiàn)超時(shí),此時(shí)我們傳遞 1000 毫秒來(lái)試試

控制臺(tái)輸出如下,輸出了超時(shí)信息,且通過(guò)前兩行輸出看出主線程瞬間就結(jié)束了,不會(huì)被請(qǐng)求阻塞。

主線程:Thread[http-nio-8080-exec-1,5,main],1624892109695,開始
主線程:Thread[http-nio-8080-exec-1,5,main],1624892109695,結(jié)束,耗時(shí)(ms):0
超時(shí)了

6、總結(jié)

當(dāng)接口中有大量的耗時(shí)的操作,且這些耗時(shí)的操作讓線程處于等待狀態(tài)時(shí),此時(shí)為了提升系統(tǒng)的性能,可以將接口調(diào)整為異步處理的方式。

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

  • 2021年最新Redis面試題匯總(2)

    2021年最新Redis面試題匯總(2)

    在程序員面試過(guò)程中redis相關(guān)的知識(shí)是常被問(wèn)到的話題。這篇文章主要介紹了幾道Redis面試題,整理一下分享給大家,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Spring Boot 使用Druid詳解

    Spring Boot 使用Druid詳解

    本篇文章主要介紹了Spring Boot 使用Druid配置詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • java環(huán)境變量配置超詳細(xì)圖文教程

    java環(huán)境變量配置超詳細(xì)圖文教程

    在我們學(xué)習(xí)Java語(yǔ)言的時(shí)候,要在命令提示符里運(yùn)用Java和Javac,用到這兩個(gè)命令的時(shí)候就要配置Java環(huán)節(jié)變量才可以,這篇文章主要給大家介紹了關(guān)于java環(huán)境變量配置的相關(guān)資料,需要的朋友可以參考下
    2023-10-10
  • Java多線程之線程池七個(gè)參數(shù)詳解

    Java多線程之線程池七個(gè)參數(shù)詳解

    這篇文章主要介紹了Java多線程之線程池七個(gè)參數(shù)詳解,文中有很詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-04-04
  • MyBatis執(zhí)行SQL的兩種方式小結(jié)

    MyBatis執(zhí)行SQL的兩種方式小結(jié)

    本文主要介紹了MyBatis執(zhí)行SQL的兩種方式小結(jié),主要包括SqlSession 發(fā)送SQL和SqlSession獲取Mapper接口,通過(guò)Mapper接口發(fā)送SQL,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • Java后端實(shí)現(xiàn)MD5加密的方法

    Java后端實(shí)現(xiàn)MD5加密的方法

    有的時(shí)候因?yàn)闃I(yè)務(wù)的需要,我們要制作關(guān)于密碼的修改功能。而關(guān)于密碼的加密一般都是用MD5,那么這篇文章將介紹如何在Java的后端實(shí)現(xiàn)MD5加密,有需要的可以參考借鑒。
    2016-08-08
  • Java重載構(gòu)造原理與用法詳解

    Java重載構(gòu)造原理與用法詳解

    這篇文章主要介紹了Java重載構(gòu)造原理與用法,結(jié)合實(shí)例形式分析了java可變參數(shù)、方法重載、構(gòu)造器等相關(guān)概念、原理及操作注意事項(xiàng),需要的朋友可以參考下
    2020-02-02
  • Java 中 String,StringBuffer 和 StringBuilder 的區(qū)別及用法

    Java 中 String,StringBuffer 和 StringBuilder 的區(qū)別及用法

    這篇文章主要介紹了Java 中 String,StringBuffer 和 StringBuilder 的區(qū)別及用法的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(39)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(39)

    下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望可以幫到你
    2021-07-07
  • 最新評(píng)論