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

Spring @async方法如何添加注解實(shí)現(xiàn)異步調(diào)用

 更新時(shí)間:2020年01月15日 14:56:05   作者:沫小淘  
這篇文章主要介紹了Spring @async方法如何添加注解實(shí)現(xiàn)異步調(diào)用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

這篇文章主要介紹了Spring @async方法如何添加注解實(shí)現(xiàn)異步調(diào)用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

在我們使用spring框架的過程中,在很多時(shí)候我們會(huì)使用@async注解來異步執(zhí)行某一些方法,提高系統(tǒng)的執(zhí)行效率。今天我們來探討下 spring 是如何完成這個(gè)功能的。

spring 在掃描bean的時(shí)候會(huì)掃描方法上是否包含@async的注解,如果包含的,spring會(huì)為這個(gè)bean動(dòng)態(tài)的生成一個(gè)子類,我們稱之為代理類(?), 代理類是繼承我們所寫的bean的,然后把代理類注入進(jìn)來,那此時(shí),在執(zhí)行此方法的時(shí)候,會(huì)到代理類中,代理類判斷了此方法需要異步執(zhí)行,就不會(huì)調(diào)用父類 (我們?cè)緦懙腷ean)的對(duì)應(yīng)方法。spring自己維護(hù)了一個(gè)隊(duì)列,他會(huì)把需要執(zhí)行的方法,放入隊(duì)列中,等待線程池去讀取這個(gè)隊(duì)列,完成方法的執(zhí)行, 從而完成了異步的功能。

我們可以關(guān)注到再配置task的時(shí)候,是有參數(shù)讓我們配置線程池的數(shù)量的。因?yàn)檫@種實(shí)現(xiàn)方法,所以在同一個(gè)類中的方法調(diào)用,添加@async注解是失效的!,原因是當(dāng)你在同一個(gè)類中的時(shí)候,方法調(diào)用是在類體內(nèi)執(zhí)行的,spring無法截獲這個(gè)方法調(diào)用。

那在深入一步,spring為我們提供了AOP,面向切面的功能。他的原理和異步注解的原理是類似的,spring在啟動(dòng)容器的時(shí)候,會(huì)掃描切面所定義的 類。在這些類被注入的時(shí)候,所注入的也是代理類,當(dāng)你調(diào)用這些方法的時(shí)候,本質(zhì)上是調(diào)用的代理類。通過代理類再去執(zhí)行父類相對(duì)應(yīng)的方法,那spring只 需要在調(diào)用之前和之后執(zhí)行某段代碼就完成了AOP的實(shí)現(xiàn)了!

那最后我們還有一個(gè)問題,spring是如何動(dòng)態(tài)的生成某一個(gè)類的子類的?代理類?

簡(jiǎn)單介紹:

Spring為任務(wù)調(diào)度與異步方法執(zhí)行提供了注解支持。通過在方法上設(shè)置@Async注解,可使得方法被異步調(diào)用。也就是說調(diào)用者會(huì)在調(diào)用時(shí)立即返回,而被調(diào)用方法的實(shí)際執(zhí)行是交給Spring的TaskExecutor來完成。

開啟@Async注解:

<task:annotation-driven executor="annotationExecutor" />
<!-- 支持 @Async 注解 -->
<task:executor id="annotationExecutor" pool-size="20"/>

同時(shí)加入<context:component-scan />掃描注解。

為了比較,先來一個(gè)同步調(diào)用:

@Component
public class TestAsyncBean {
  public void sayHello4() throws InterruptedException {
    Thread.sleep(2 * 1000);//網(wǎng)絡(luò)連接中 。。。消息發(fā)送中。。。
    System.out.println("我愛你啊!");
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
  @Test
  public void test_sayHello4() throws InterruptedException, ExecutionException {
    System.out.println("你不愛我了么?");
    testAsyncBean.sayHello4();
    System.out.println("回的這么慢, 你肯定不愛我了, 我們還是分手吧。。。");
    Thread.sleep(3 * 1000);// 不讓主進(jìn)程過早結(jié)束
  }
}

輸出結(jié)果:

你不愛我了么?
我愛你啊!
回的這么慢, 你肯定不愛我了, 我們還是分手吧。。。 

 同步調(diào)用會(huì)按代碼順序依次進(jìn)行下去,如果哪里需要等待,那么就阻塞在那里,不再向下繼續(xù)進(jìn)行。

使用@Async的異步調(diào)用:

@Component
public class TestAsyncBean {
  @Async
  public void sayHello3() throws InterruptedException {
    Thread.sleep(2 * 1000);//網(wǎng)絡(luò)連接中 。。。消息發(fā)送中。。。
    System.out.println("我愛你啊!");
  }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
  @Autowired
  private TestAsyncBean testAsyncBean;
  @Test
  public void test_sayHello3() throws InterruptedException, ExecutionException {
    System.out.println("你不愛我了么?");
    testAsyncBean.sayHello3();
    System.out.println("你竟無話可說, 我們分手吧。。。");
    Thread.sleep(3 * 1000);// 不讓主進(jìn)程過早結(jié)束
  }
}

輸出結(jié)果:

你不愛我了么?
你竟無話可說, 我們分手吧。。。
我愛你啊!

異步調(diào)用,通過開啟新的線程來執(zhí)行調(diào)用的方法,不影響主線程。異步方法實(shí)際的執(zhí)行交給了Spring的TaskExecutor來完成。

上面這種方式是沒有返回值的,下面嘗試有返回值的異步調(diào)用:

@Component
public class TestAsyncBean {
  @Async
  public String sayHello2() throws InterruptedException {
    Thread.sleep(2 * 1000);//網(wǎng)絡(luò)連接中 。。。消息發(fā)送中。。。
    return "我愛你啊!";// 調(diào)用方調(diào)用后會(huì)立即返回,所以返回null
  }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
  @Autowired
  private TestAsyncBean testAsyncBean;
  @Test
  public void test_sayHello2() throws InterruptedException, ExecutionException {
    System.out.println("你不愛我了么?");
    System.out.println(testAsyncBean.sayHello2());
    System.out.println("你說的啥? 我們還是分手吧。。。");
    Thread.sleep(3 * 1000);// 不讓主進(jìn)程過早結(jié)束
  }
}

輸出結(jié)果:

你不愛我了么?
null
你說的啥? 我們還是分手吧。。。

通過直接獲取返回值得方式是不行的,這里就需要用到異步回調(diào),異步方法返回值必須為Future<>,就像Callable與Future。

下面通過AsyncResult<>來獲得異步調(diào)用的返回值:

@Component
public class TestAsyncBean {
  @Async
  public Future<String> sayHello1() throws InterruptedException {
    int thinking = 2;
    Thread.sleep(thinking * 1000);//網(wǎng)絡(luò)連接中 。。。消息發(fā)送中。。。
    System.out.println("我愛你啊!");
    return new AsyncResult<String>("發(fā)送消息用了"+thinking+"秒");
  }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
  @Autowired
  private TestAsyncBean testAsyncBean;
  @Test
  public void test_sayHello1() throws InterruptedException, ExecutionException {
    Future<String> future = null;
    System.out.println("你不愛我了么?");
    future = testAsyncBean.sayHello1();
    System.out.println("你竟無話可說, 我們分手吧。。。");
    Thread.sleep(3 * 1000);// 不讓主進(jìn)程過早結(jié)束
    System.out.println(future.get());
  }
}

輸出結(jié)果:

你不愛我了么?
你竟無話可說, 我們分手吧。。。
我愛你啊!

發(fā)送消息用了2秒

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 基于java Servlet編碼/異常處理(詳解)

    基于java Servlet編碼/異常處理(詳解)

    下面小編就為大家?guī)硪黄趈ava Servlet編碼/異常處理(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • MyBatisPlus之id生成策略的方法

    MyBatisPlus之id生成策略的方法

    本文主要介紹了MyBatisPlus之id生成策略的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Mybatis?ResultMap和分頁(yè)操作示例詳解

    Mybatis?ResultMap和分頁(yè)操作示例詳解

    這篇文章主要為大家介紹了Mybatis?ResultMap和分頁(yè)操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • springboot中redis操作Hash踩坑解決

    springboot中redis操作Hash踩坑解決

    本文主要介紹了springboot中redis操作Hash踩坑解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • java基礎(chǔ)學(xué)習(xí)筆記之泛型

    java基礎(chǔ)學(xué)習(xí)筆記之泛型

    所謂泛型,就是變量類型的參數(shù)化。泛型是JDK1.5中一個(gè)最重要的特征。通過引入泛型,我們將獲得編譯時(shí)類型的安全和運(yùn)行時(shí)更小的拋出ClassCastException的可能。在JDK1.5中,你可以聲明一個(gè)集合將接收/返回的對(duì)象的類型。
    2016-02-02
  • 詳細(xì)聊聊SpringBoot中動(dòng)態(tài)切換數(shù)據(jù)源的方法

    詳細(xì)聊聊SpringBoot中動(dòng)態(tài)切換數(shù)據(jù)源的方法

    在大型分布式項(xiàng)目中,經(jīng)常會(huì)出現(xiàn)多數(shù)據(jù)源的情況,下面這篇文章主要給大家介紹了關(guān)于SpringBoot中動(dòng)態(tài)切換數(shù)據(jù)源的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09
  • springboot 單文件上傳的實(shí)現(xiàn)步驟

    springboot 單文件上傳的實(shí)現(xiàn)步驟

    這篇文章主要介紹了springboot實(shí)現(xiàn)單文件上傳的方法,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下
    2021-02-02
  • Java 10的10個(gè)新特性總結(jié)

    Java 10的10個(gè)新特性總結(jié)

    這篇文章我們給大家整理了關(guān)于Java 10的10個(gè)新特性以及相關(guān)要點(diǎn)內(nèi)容,有興趣的朋友們可以參考下。
    2018-08-08
  • 使用javax.sound實(shí)現(xiàn)簡(jiǎn)單音頻播放

    使用javax.sound實(shí)現(xiàn)簡(jiǎn)單音頻播放

    這篇文章主要為大家詳細(xì)介紹了使用javax.sound實(shí)現(xiàn)簡(jiǎn)單音頻播放,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 如何通過javacv實(shí)現(xiàn)圖片去水?。ǜ酱a)

    如何通過javacv實(shí)現(xiàn)圖片去水?。ǜ酱a)

    這篇文章主要介紹了如何通過javacv實(shí)現(xiàn)圖片去水?。ǜ酱a),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07

最新評(píng)論