Spring/Spring Boot中使用@Async
當我們在調用某些耗時的方法,比如發起第三方調用時而不關心他的傳回值,可以采用@Async來實作異步調用。極大的提升程式的響應速度。
在以往的程式設計方法中我們一般都是開啟另一個線程去處理類似的場景,而在Spring 3.x之後則可以使用@Async。
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {
String value() default "";
}
可以看到@Async可以修飾在方法和類上。當修飾方法時,該方法則成為異步方法,這些方法在執行的時候将會被獨立的線程去執行。
在Spring和Spring Boot中啟用@Async
在啟動類上添加注解:@EnableAsync
在相應的方法上添加注解:@Async
需要處理傳回值
如果在使用了@Async的方法時還需要處理它的傳回值,那麼需要用到
Future
類。
@Async
public Future<String> asyncMethodWithReturnType() {
System.out.println("Execute method asynchronously - "
+ Thread.currentThread().getName());
try {
Thread.sleep(5000);
return new AsyncResult<String>("hello world !!!!");
} catch (InterruptedException e) {
//
}
return null;
}
以上是異步方法,調用該方法時應該以如下方式調用:
public void testAsyncAnnotationForMethodsWithReturnType()
throws InterruptedException, ExecutionException {
System.out.println("Invoking an asynchronous method. "
+ Thread.currentThread().getName());
Future<String> future = asyncAnnotationExample.asyncMethodWithReturnType();
while (true) { ///這裡使用了循環判斷,等待擷取結果資訊
if (future.isDone()) { //判斷是否執行完畢
System.out.println("Result from asynchronous process - " + future.get());
break;
}
System.out.println("Continue doing something else. ");
Thread.sleep(1000);
}
}
通過
while true
來循環判斷異步方法是否正常傳回,但是這樣的代碼在正常情況下完全沒有必要性,不如直接寫成同步調用。
異常處理
在異步方法中,如果出現了異常,對于調用者而言是無法感覺的。如果确實需要處理異常,則需要自定義實作AsyncTaskExecutor。
事務處理
如果想要在異步方法中實作事務,則需要把需要事務管理的方法放到異步方法内部,在内部被調用的方法上添加@Transactional。
例如:方法A,使用了@Async/@Transactional來修飾,但是無法達到事務控制的目的。
方法B,使用了@Async修飾,B中調用了C、D,C/D分别使用@Transactional來修飾,可以達到事務控制的目的。