SpringBoot異步調(diào)用@Async

一. 什么是異步調(diào)用拐云?

異步調(diào)用是相對于同步調(diào)用而言的留潦,同步調(diào)用是指程序按預(yù)定順序一步步執(zhí)行,每一步必須等到上一步執(zhí)行完后才能執(zhí)行觉啊,異步調(diào)用則無需等待上一步程序執(zhí)行完即可執(zhí)行能犯。

二. 如何實(shí)現(xiàn)異步調(diào)用鲫骗?

多線程,這是很多人第一眼想到的關(guān)鍵詞踩晶,沒錯执泰,多線程就是一種實(shí)現(xiàn)異步調(diào)用的方式。在非spring目項(xiàng)目中我們要實(shí)現(xiàn)異步調(diào)用的就是使用多線程方式渡蜻,可以自己實(shí)現(xiàn)Runable接口或者集成Thread類坦胶,或者使用jdk1.5以上提供了的Executors線程池。在spring 3.x之后,就已經(jīng)內(nèi)置了@Async來完美解決這個問題顿苇,下面將介紹在springboot中如何使用@Async。

三. 舉例說明(無須知道執(zhí)行結(jié)果):

1税弃、pom.xml中導(dǎo)入必要的依賴:

  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>

    <dependencies>
        <!-- SpringBoot 核心組件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
    </dependencies>

2纪岁、寫一個springboot的啟動類:

啟動類里面使用@EnableAsync注解開啟功能,自動掃描

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync
public class SpringBootAsyncApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootAsyncApplication.class, args);
    }
}

3则果、建一個service包幔翰,然后新建一個UserService類:

  • 要在異步任務(wù)的類上寫@Component
  • 在定義異步任務(wù)類寫@Async(寫在類上代表整個類都是異步,在方法加上代表該類異步執(zhí)行)
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Async
    public void sendSms(){
        System.out.println("####sendSms####   2");
        IntStream.range(0, 5).forEach(d -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println("####sendSms####   3");
    }

}

4西壮、建一個controller包遗增,然后新建一個IndexController類,用來獲取請求:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.jeffrey.service.UserService;

@RestController
public class IndexController {
    
    @Autowired
    private UserService userService;
    
    @RequestMapping("/async")
    public String async(){
        System.out.println("####IndexController####   1");
        userService.sendSms();
        System.out.println("####IndexController####   4");
        return "success";
    }
    
}

先注掉@EnableAsync和@Async兩個注解款青,看下同步調(diào)用執(zhí)行的效果做修。執(zhí)行結(jié)果如下:

####IndexController####   1
####sendSms####   2
####sendSms####   3
####IndexController####   4

對于sendSms方法,我們并不關(guān)注它什么時候執(zhí)行完抡草,所以可以采用異步的方式去執(zhí)行饰及。放開@EnableAsync和@Async兩個注解,執(zhí)行結(jié)果如下:

####IndexController####   1
####IndexController####   4
####sendSms####   2
####sendSms####   3

總結(jié):使用了@Async的方法康震,會被當(dāng)成是一個子線程燎含,所有整個sendSms方法,會在主線程執(zhí)行完了之后執(zhí)行

四. 舉例說明(須知道執(zhí)行結(jié)果):

基于上面例子腿短,這里只貼核心代碼

1屏箍、啟動類

@SpringBootApplication
@EnableAsync   //開啟異步任務(wù)
public class MainApplication {

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

2、異步類

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

import java.util.concurrent.Future;

/**
 * @ClassName AsyncTestTask
 * @Author jeffrey
 * @Description 異步任務(wù)業(yè)務(wù)類
 **/
@Component
@Async
public class AsyncTestTask {
    //獲取異步結(jié)果
    public Future<String> task4() throws InterruptedException{
        long begin = System.currentTimeMillis();
        Thread.sleep(2000L);
        long end = System.currentTimeMillis();
        System.out.println("任務(wù)4耗時="+(end-begin));
        return new AsyncResult<String>("任務(wù)4");
    }


    public Future<String> task5() throws InterruptedException{
        long begin = System.currentTimeMillis();
        Thread.sleep(3000L);
        long end = System.currentTimeMillis();
        System.out.println("任務(wù)5耗時="+(end-begin));
        return new AsyncResult<String>("任務(wù)5");
    }

    public Future<String> task6() throws InterruptedException{
        long begin = System.currentTimeMillis();
        Thread.sleep(1000L);
        long end = System.currentTimeMillis();
        System.out.println("任務(wù)6耗時="+(end-begin));
        return new AsyncResult<String>("任務(wù)6");
    }
}

3橘忱、controller類

import com.ceair.service.AsyncTestTask;
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;

import java.util.concurrent.Future;

/**
 * @ClassName UserController
 * @Author jeffrey
 * @Description User
 **/

@RestController
@RequestMapping("/api")
public class UserController {
    @Autowired
    private AsyncTestTask asyncTestTask;

    @GetMapping("userAsyncTask")
    public String exeTask() throws InterruptedException{

        long begin = System.currentTimeMillis();

        Future<String> task4 = asyncTestTask.task4();
        Future<String> task5 = asyncTestTask.task5();
        Future<String> task6 = asyncTestTask.task6();

        //如果都執(zhí)行往就可以跳出循環(huán),isDone方法如果此任務(wù)完成赴魁,true
        for(;;){
            if (task4.isDone() && task5.isDone() && task6.isDone()) {
                break;
            }
        }

        long end = System.currentTimeMillis();
        long total = end-begin;
        System.out.println("執(zhí)行總耗時="+total);
        return String.valueOf(total);
    }
}

執(zhí)行結(jié)果如下:

任務(wù)6耗時=1000
任務(wù)4耗時=2000
任務(wù)5耗時=3000
執(zhí)行總耗時=3012

總結(jié):
從上面示例我們可以看出:如果同步方法,那我們需要6秒鹦付,而異步執(zhí)行尚粘,我們只需要3秒左右,這就是異步的作用敲长。
1)要把異步任務(wù)封裝到類里面郎嫁,不能直接寫到Controller
2)增加Future<String> 返回結(jié)果 AsyncResult<String>("task執(zhí)行完成");
3)如果需要拿到結(jié)果 需要判斷全部的 task.isDone()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市祈噪,隨后出現(xiàn)的幾起案子泽铛,更是在濱河造成了極大的恐慌,老刑警劉巖辑鲤,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盔腔,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)弛随,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進(jìn)店門瓢喉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人舀透,你說我怎么就攤上這事栓票。” “怎么了愕够?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵走贪,是天一觀的道長。 經(jīng)常有香客問我惑芭,道長坠狡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任遂跟,我火速辦了婚禮逃沿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘漩勤。我一直安慰自己感挥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布越败。 她就那樣靜靜地躺著触幼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪究飞。 梳的紋絲不亂的頭發(fā)上置谦,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天,我揣著相機(jī)與錄音亿傅,去河邊找鬼媒峡。 笑死,一個胖子當(dāng)著我的面吹牛葵擎,可吹牛的內(nèi)容都是我干的谅阿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼酬滤,長吁一口氣:“原來是場噩夢啊……” “哼签餐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起盯串,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤氯檐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后体捏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冠摄,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡糯崎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了河泳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沃呢。...
    茶點(diǎn)故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拆挥,靈堂內(nèi)的尸體忽然破棺而出樟插,到底是詐尸還是另有隱情,我是刑警寧澤竿刁,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站搪缨,受9級特大地震影響食拜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜副编,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一负甸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧痹届,春花似錦呻待、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至柴淘,卻和暖如春迫淹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背为严。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工敛熬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人第股。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓应民,卻偏偏與公主長得像,于是被迫代替她去往敵國和親夕吻。 傳聞我的和親對象是個殘疾皇子诲锹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評論 2 359

推薦閱讀更多精彩內(nèi)容