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

詳解springboot使用異步注解@Async獲取執(zhí)行結(jié)果的坑

 更新時(shí)間:2021年08月22日 09:31:21   作者:北漂程序員  
本文主要介紹了springboot使用異步注解@Async獲取執(zhí)行結(jié)果的坑,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、引言

在java后端開(kāi)發(fā)中經(jīng)常會(huì)碰到處理多個(gè)任務(wù)的情況,比如一個(gè)方法中要調(diào)用多個(gè)請(qǐng)求,然后把多個(gè)請(qǐng)求的結(jié)果合并后統(tǒng)一返回,一般情況下調(diào)用其他的請(qǐng)求一般都是同步的,也就是每個(gè)請(qǐng)求都是阻塞的,那么這個(gè)處理時(shí)間必定是很長(zhǎng)的,有沒(méi)有一種方法可以讓多個(gè)請(qǐng)求異步處理那,答案是有的。

springboot中提供了很便利的方式可以解決上面的問(wèn)題,那就是異步注解@Async。正確的使用該注解可以使你的程序飛起,相反如果使用不當(dāng)那么并不會(huì)取到理想的效果。

二、獲取異步執(zhí)行結(jié)果

1、環(huán)境介紹

下面是我的controller,SyncController.java

package com.atssg.controller;

import com.atssg.service.MySyncService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@Slf4j
@RestController
@RequestMapping("/sync")
public class SyncController {
    @Autowired
    private MySyncService syncService;

    @GetMapping(value = "/test")

    public String test() {
        String str=null;
        try {

            log.info("start");
            str = syncService.asyncMethod();
            log.info("str:{}", str);
            return str;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return str;
    }
}

在controller中就是調(diào)用下層的方法并返回,再看service層的類MySyncService.java

package com.atssg.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@Service
public class MySyncService {
    @Autowired
    private SyncService syncService;

    /**
     * 異步方法
     *
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public String asyncMethod() throws InterruptedException, ExecutionException {

        Future<String> result1 = syncService.method1("I");
        Future<String> result2 = syncService.method2("love");
        Future<String> result3 = syncService.method3("async");

        String str = result1.get();
        String str2 = result2.get();
        String str3 = result3.get();

        String result = str + str2 + str3;

        return result;
    }

    /**
     * 同步方法
     *
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public String syncMethod() throws InterruptedException, ExecutionException {
        /*同步寫(xiě)法*/
        String str = syncService.method1("I").get();
        String str2 = syncService.method2("love").get();
        String str3 = syncService.method3("async").get();
        return str + str2 + str3;
    }
}

上面便是service類,僅僅是調(diào)用下次異步層的方法,并取得返回值。上面類中有兩個(gè)方法,其寫(xiě)法也類似但結(jié)果卻大不相同,后面詳說(shuō)。

下面是異步層的方法,SyncService.java

package com.atssg.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;

@Service
@Async
public class SyncService {

    //@Async
    public Future<String> method1(String str) throws InterruptedException {
       Thread.sleep(1000*10);
        return new AsyncResult<>( str);
    }
    //@Async
    public Future<String> method2(String str) throws InterruptedException {
        Thread.sleep(1000*5);
        return new AsyncResult<>(str);
    }
   // @Async
    public Future<String> method3(String str) throws InterruptedException {
        Thread.sleep(1000*15);
        return new AsyncResult<>(str);
    }
}

該類使用@Async注解,表明該類中所有的方法都是異步執(zhí)行的,其中@Async可修飾類也可以修飾方法。

這便是所有的環(huán)境。

2、錯(cuò)誤的方式

在MySyncService中有兩個(gè)方法,先看其中一個(gè)方法

public String syncMethod() throws InterruptedException, ExecutionException {
        /*同步寫(xiě)法*/
        String str = syncService.method1("I").get();
        String str2 = syncService.method2("love").get();
        String str3 = syncService.method3("async").get();
        return str + str2 + str3;
    }

這種寫(xiě)法是調(diào)用異步方法后立即調(diào)用get()方法,即獲取結(jié)果,下面看測(cè)試結(jié)果,在controllor中調(diào)用該方法,下面看執(zhí)行結(jié)果

2021-08-21 11:06:28.612  INFO 3584 --- [nio-8080-exec-1] com.atssg.controller.SyncController      : start
2021-08-21 11:06:58.651  INFO 3584 --- [nio-8080-exec-1] com.atssg.controller.SyncController      : str:Iloveasync

可以看到共執(zhí)行了30s,在異步層的方法中的三個(gè)方法如下,

//@Async
    public Future<String> method1(String str) throws InterruptedException {
       Thread.sleep(1000*10);
        return new AsyncResult<>( str);
    }
    //@Async
    public Future<String> method2(String str) throws InterruptedException {
        Thread.sleep(1000*5);
        return new AsyncResult<>(str);
    }
   // @Async
    public Future<String> method3(String str) throws InterruptedException {
        Thread.sleep(1000*15);
        return new AsyncResult<>(str);
    }

可以看到這三個(gè)方法分別是睡眠10s、5s、15s,這就很好理解了syncMethod()方法中的寫(xiě)法是同步的,未達(dá)到異步的目的,切記調(diào)用完異步方法進(jìn)接著調(diào)用get()方法不是異步的方式,而是同步的。

3、正確方式

上面看了錯(cuò)誤的用法,下面看正確的方式,

 public String asyncMethod() throws InterruptedException, ExecutionException {

        Future<String> result1 = syncService.method1("I");
        Future<String> result2 = syncService.method2("love");
        Future<String> result3 = syncService.method3("async");

        String str = result1.get();
        String str2 = result2.get();
        String str3 = result3.get();

        String result = str + str2 + str3;

        return result;
    }

這種方式是首先調(diào)用異步方法,然后分別調(diào)用get()方法,取得執(zhí)行結(jié)果。下面看測(cè)試結(jié)果

2021-08-21 11:17:23.516  INFO 3248 --- [nio-8080-exec-1] com.atssg.controller.SyncController      : start
2021-08-21 11:17:38.535  INFO 3248 --- [nio-8080-exec-1] com.atssg.controller.SyncController      : str:Iloveasync

執(zhí)行時(shí)間未15s,這就很好解釋了,異步層的三個(gè)方法,分別睡眠的時(shí)間是10s、5s、15s,既然是異步執(zhí)行的,那么總的執(zhí)行時(shí)間肯定是三個(gè)方法中最長(zhǎng)的那個(gè),符合測(cè)試結(jié)果。這才@Async正確的打開(kāi)姿勢(shì)。

三、異步執(zhí)行@Async注解

@Async注解的定義如下,

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {
    String value() default "";
}

可以看到該注解可以用在類及方法上,用在類上表示類中的所有方法都是異步的,用在方法上表示該方法是異步的。

四、總結(jié)

今天的文章分享到這里,主要分享了關(guān)于@Async注解在獲取執(zhí)行結(jié)果的時(shí)候的坑,一定要先調(diào)用異步方法,然后再調(diào)用get()方法,獲取結(jié)果,其中g(shù)et方法還有一個(gè)重載的,可以設(shè)置超時(shí)時(shí)間,即超過(guò)設(shè)置的超時(shí)時(shí)間便返回,不再等待,各位小伙伴可以自己試驗(yàn)。

 V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

下次繼續(xù)分享有關(guān)@Async注解使用的一些小細(xì)節(jié),歡迎持續(xù)關(guān)注。

到此這篇關(guān)于詳解springboot使用異步注解@Async獲取執(zhí)行結(jié)果的坑的文章就介紹到這了,更多相關(guān)springboot使用異步注解@Async 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Servlet實(shí)現(xiàn)分頁(yè)效果

    Servlet實(shí)現(xiàn)分頁(yè)效果

    這篇文章主要為大家詳細(xì)介紹了Servlet實(shí)現(xiàn)分頁(yè)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 執(zhí)行java請(qǐng)求時(shí)導(dǎo)致在腳本執(zhí)行結(jié)束時(shí)JVM無(wú)法退出

    執(zhí)行java請(qǐng)求時(shí)導(dǎo)致在腳本執(zhí)行結(jié)束時(shí)JVM無(wú)法退出

    這篇文章主要介紹了執(zhí)行java請(qǐng)求,導(dǎo)致在腳本執(zhí)行結(jié)束時(shí)JVM無(wú)法退出問(wèn)題,本文通過(guò)原因分析給出解決方案,需要的朋友可以參考下
    2020-02-02
  • 8張圖帶你全面了解Java?kafka的核心機(jī)制

    8張圖帶你全面了解Java?kafka的核心機(jī)制

    kafka是目前企業(yè)中很常用的消息隊(duì)列產(chǎn)品,可以用于削峰、解耦、異步通信,本文就通過(guò)幾張圖帶大家全面認(rèn)識(shí)一下kafka,現(xiàn)在我們不妨帶入kafka設(shè)計(jì)者的角度去思考該如何設(shè)計(jì),它的架構(gòu)是怎么樣的、都有哪些組件組成、如何進(jìn)行擴(kuò)展等等,需要的朋友可以參考下
    2023-05-05
  • Spring創(chuàng)建bean實(shí)例的幾種方式分享

    Spring創(chuàng)建bean實(shí)例的幾種方式分享

    這篇文章主要介紹了Spring創(chuàng)建bean實(shí)例的幾種方式分享,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07
  • Java實(shí)現(xiàn)二分查找BinarySearch算法

    Java實(shí)現(xiàn)二分查找BinarySearch算法

    這篇文章主要介紹了Java實(shí)現(xiàn)二分查找BinarySearch算法,二分查找針對(duì)的是一個(gè)有序的數(shù)據(jù)集合,每次都通過(guò)跟區(qū)間的中間元素對(duì)比,將待查找的區(qū)間縮小為之前的一半,直到找到要查找的元素,或者區(qū)間被縮小為 0,需要的朋友可以參考下
    2023-12-12
  • 基于SpringBoot+Redis的Session共享與單點(diǎn)登錄詳解

    基于SpringBoot+Redis的Session共享與單點(diǎn)登錄詳解

    這篇文章主要介紹了基于SpringBoot+Redis的Session共享與單點(diǎn)登錄,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • java實(shí)現(xiàn)登錄驗(yàn)證碼功能

    java實(shí)現(xiàn)登錄驗(yàn)證碼功能

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)登錄驗(yàn)證碼功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • springboot 啟動(dòng)時(shí)初始化數(shù)據(jù)庫(kù)的步驟

    springboot 啟動(dòng)時(shí)初始化數(shù)據(jù)庫(kù)的步驟

    這篇文章主要介紹了springboot 啟動(dòng)時(shí)初始化數(shù)據(jù)庫(kù)的步驟,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下
    2021-01-01
  • GsonFormat快速生成JSon實(shí)體類的實(shí)現(xiàn)

    GsonFormat快速生成JSon實(shí)體類的實(shí)現(xiàn)

    GsonFormat主要用于使用Gson庫(kù)將JSONObject格式的String?解析成實(shí)體,本文主要介紹了GsonFormat快速生成JSon實(shí)體類的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-05-05
  • Java8實(shí)現(xiàn)對(duì)List<Integer>的求和

    Java8實(shí)現(xiàn)對(duì)List<Integer>的求和

    這篇文章主要介紹了Java8實(shí)現(xiàn)對(duì)List<Integer>的求和方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05

最新評(píng)論