2018-03-13 Spring中的異步調(diào)用

異步方法調(diào)用

異步方法調(diào)用或異步方法模式是(多線程)面向?qū)ο蟪绦蛟O(shè)計(jì)中用于異步調(diào)用對象的潛在的長期運(yùn)行
方法的一種設(shè)計(jì)模式。在說異步方法調(diào)用時(shí),我們有必要再來看一下同步方法調(diào)用。

同步方法調(diào)用在程序繼續(xù)執(zhí)行之前需要等待同步方法全部執(zhí)行完畢返回結(jié)果。

同步調(diào)用是一種典型的阻塞式調(diào)用,無論如何我們只能等代上一個(gè)任務(wù)完成后,才能繼續(xù)后面的任務(wù)。
而異步方法調(diào)用,只需要發(fā)送調(diào)用任務(wù)的指令,調(diào)用者無需等待被調(diào)用的任務(wù)完全執(zhí)行完成,就
可以繼續(xù)執(zhí)行后面的任務(wù)。

Java中異步調(diào)用的處理方式

在Java中,一般情況下都是通過創(chuàng)建獨(dú)立的線程去完成異步調(diào)用的邏輯,主線程與其他線程執(zhí)行
不同的流程,從而避免主線程被阻塞。

Spring中的異步調(diào)用@Async

在Spring中,基于@Async標(biāo)注的方法,就被轉(zhuǎn)化為異步方法。這些方法在調(diào)用時(shí),會在獨(dú)立的線程
中執(zhí)行,調(diào)用者無需等待其調(diào)用完成,就可以繼續(xù)向下執(zhí)行。

配置開啟@Async

Java代碼開啟

@Configuration
@EnableAsync
public class SpringAsyncConfig { ... }

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

XML配置開啟

<task:executor id="myexecutor" pool-size="5"  />
<task:annotation-driven executor="myexecutor"/>

標(biāo)注方法

@Async標(biāo)注無返回值的方法

@Async  //標(biāo)注使用
public void asyncMethodWithVoidReturnType() {
    System.out.println("Execute Void Return Type Method");
}

@Async標(biāo)注有返回值的方法

@Async
public Future<String> asyncMethodWithReturnType() {
    System.out.println("Execute Has Return Type Method");
    try {
        Thread.sleep(5000);
        return new AsyncResult<String>("Return String");
    } catch (InterruptedException e) {
        //
    }

    return null;
}

這里方法的返回類型是Future接口,F(xiàn)uture接口是Java線程Future模式的實(shí)現(xiàn),用來進(jìn)行異步計(jì)算。
Future模式可以簡單的理解為,調(diào)用者將任務(wù)提交給Future,F(xiàn)uture去執(zhí)行任務(wù),在執(zhí)行期間
調(diào)用者可以繼續(xù)執(zhí)行其他任務(wù),在一段時(shí)間后,調(diào)用者可以通過Future獲取到任務(wù)的執(zhí)行結(jié)果。

獲取方法返回值:

Future<String> future = asyncService.asyncMethodWithReturnType();
while (true) {
    if (future.isDone()) {  //判斷是否執(zhí)行完畢
        System.out.println("Receive Return Value" + future.get());
        break;
    }
    System.out.println("Continue Waiting");
    Thread.sleep(1000);
}

@Async方法中的異常處理

配置AsyncUncaughtExceptionHandler 捕獲無返回值方法中的異常

@EnableAsync
@Configuration
@Slf4j
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(8);
        executor.setMaxPoolSize(16);
        executor.setQueueCapacity(64);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setThreadNamePrefix("SpringAsyncThread-");
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SpringAsyncExceptionHandler();
    }

    class SpringAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
            log.error("Exception in async method - {}", throwable.getMessage());
        }
    }
}

有返回值的異步方法的異常捕獲

對于有返回值的異步方法,返回值應(yīng)當(dāng)是AsyncResult類的對象,或者是Future接口的子類,
這樣在調(diào)用Future的get()方法時(shí),就可以捕獲ExcecutionException。

@Async方法中的事務(wù)處理

在被@Async標(biāo)注的方法上同時(shí)有@Transactional標(biāo)注時(shí),由于其基于異步處理操作,在對數(shù)據(jù)庫進(jìn)行操作時(shí),將無法對
事務(wù)管理進(jìn)行控制。

如果方法內(nèi)的操作需要添加事務(wù)管理,可以將相關(guān)操作提取出單獨(dú)的方法,在該方法上添加@Transactional標(biāo)注。

注意

AsyncService中包含A(), B(), C()三個(gè)異步方法,
若在AsyncService的某一方法中調(diào)用A,B,C方法是無法異步執(zhí)行的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評論 19 139
  • 接著上節(jié) condition_varible ,本節(jié)主要介紹future的內(nèi)容,練習(xí)代碼地址。本文參考http:/...
    jorion閱讀 15,062評論 1 5
  • 1 什么是異步編程 通過學(xué)習(xí)相關(guān)概念,我們逐步解釋異步編程是什么。 1.1 阻塞 程序未得到所需計(jì)算資源時(shí)被掛起的...
    hugoren閱讀 2,762評論 2 10
  • 畢業(yè)一年了,身邊的同學(xué)一個(gè)個(gè)都找到了工作,唯獨(dú)自己還在徘徊,大家都忙著實(shí)習(xí)的時(shí)候,自己卻跑去培訓(xùn)畫畫,大家因?yàn)楣ぷ?..
    清水蘭亭閱讀 188評論 0 0
  • 大年初四,徒步青龍山-白虎嶺。 雖是一條去年走過的路線,但由于今年雪小,卻是別樣風(fēng)景。 作為一名徒步界的新驢,時(shí)隔...
    小小女不才閱讀 338評論 0 0

友情鏈接更多精彩內(nèi)容