簡述
非同步呼叫 對應的是 同步呼叫,同步呼叫 指程式按照 定義順序 依次執行,每一行程式都必須等待上一行程式執行完成之後才能執行;非同步呼叫 指程式在順序執行時,不等待 非同步呼叫的語句 返回結果 就執行後面的程式。
在平常的開發中,為了使用非同步程式設計,開發者一般都是透過手動多執行緒實現。但Spring Boot 為了簡化開發流程,提供了非同步程式設計註解@Async。只要是在對應的方法上加入註解就可以實現非同步呼叫。
@Async使用
在啟動的Application中加入@EnableAsync
@EnableAsync
@SpringBootApplication
public class CrmToolApplication {
public static void main(String[] args) {
SpringApplication。run(CrmToolApplication。class, args);
}
}
在需要非同步呼叫的方法上加入@Async
@Service
@Slf4j
public class TestService {
@Async
public void asyncMethodWithNoReturnType() {
try {
Thread。sleep(3000);
} catch (InterruptedException e) {
e。printStackTrace();
}
log。info(“Async。。。{}”, this。getClass()。getSimpleName());
}
}
@Async註解原理分析
看下@EnableAsync註解的原始碼
@Target({ElementType。TYPE})
@Retention(RetentionPolicy。RUNTIME)
@Documented
@Import({AsyncConfigurationSelector。class})
public @interface EnableAsync {
Class annotation() default Annotation。class;
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode。PROXY;
int order() default 2147483647;
}
mode預設值AdviceMode。PROXY,此值含義是使用AOP實現。AOP的本質就是動態代理,動態代理的侷限在同一個類中是無法實現呼叫。
例項
@Component
@Order(1)
@Slf4j
public class StartRunner1 implements ApplicationRunner {
private final TestService testService;
public StartRunner1(TestService testService) {
this。testService = testService;
}
@Override
public void run(ApplicationArguments args) throws Exception {
log。info(“run —— {}”, this。getClass()。getSimpleName());
Thread。sleep(1000);
// testService。asyncMethodWithNoReturnType();
asyncMethodWithNoReturnType();
}
@Async
public void asyncMethodWithNoReturnType() {
try {
Thread。sleep(3000);
} catch (InterruptedException e) {
e。printStackTrace();
}
log。info(“Async。。。{}”, this。getClass()。getSimpleName());
}
}
預設情況下上面的@Async無法生效。
2020-07-18 09:09:17。269 [restartedMain] INFO c。c。t。s。StartRunner1 | 31 | - run —— StartRunner1
2020-07-18 09:09:21。290 [restartedMain] INFO c。c。t。s。StartRunner1 | 46 | - Async。。。StartRunner1
切換至呼叫TestService中的非同步方法
2020-07-18 09:10:17。464 [restartedMain] INFO c。c。t。s。StartRunner1 | 31 | - run —— StartRunner1
2020-07-18 09:10:18。472 [restartedMain] INFO c。c。t。s。StartRunner2 | 24 | - run —— StartRunner2
2020-07-18 09:10:21。492 [task-1] INFO c。c。t。s。TestService | 38 | - Async。。。TestService
可以看出執行的 執行緒發生了變化。(restartedMain,task-1)
總結
@Async 註解沒生效一般問題的就是在同一類內呼叫,Spring 的很多註解預設都是使用AOP實現,而AOP的本身就是在同一個類中無法呼叫,故此透過其實現的註解也是無法同類之內使用。