SpringBoot使用@Async注解可能會遇到的8大坑點匯總
正文
1、未啟用異步支持
Spring Boot默認情況下不啟用異步支持,確保在主配置類上添加
@EnableAsync注解以啟用異步功能。
@SpringBootApplication
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}2、沒有配置線程池
如果沒有顯式地配置線程池,Spring Boot將使用默認的SimpleAsyncTaskExecutor實現(xiàn)。
在生產環(huán)境,可能導致性能問題。建議使用自定義的線程池配置,推薦ThreadPoolTaskExecutor。
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10); // 設置核心線程數(shù)
executor.setMaxPoolSize(100); // 設置最大線程數(shù)
executor.setQueueCapacity(10); // 設置隊列容量
executor.setThreadNamePrefix("Async-"); // 設置線程名前綴
executor.initialize();
return executor;
}
// 其他配置方法...
}3、異步方法在同一個類調用
異步方法必須是通過代理機制來觸發(fā)的,因此如果在同一個類中調用異步方法,它將無法通過代理機制工作。
可以嘗試將異步方法移到另一個Bean中,然后通過依賴注入進行調用,這也是萬金油用法。
// 你的業(yè)務服務
@Service
public class MyService {
@Autowired
private AsyncService asyncService;
@Async
public void asyncMethod() {
// 異步方法邏輯...
asyncService.asyncMethod(); // 在另一個Bean中調用異步方法
}
}
// 你聲明的異步服務,這里面可以是你所有的異步方法,哪里調用直接注入即可。
@Service
public class AsyncService {
@Async
public void asyncMethod() {
// 異步方法邏輯...
}
}4、事務失效問題
@Async方法默認不會繼承父方法的事務。如果需要事務支持,請確保異步方法和調用該方法的方法都被@Transactional注解標記。
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
@Async
@Transactional
public void asyncMethod() {
// 異步方法邏輯...
myRepository.save(entity);
}
}5、異常處理
異步方法中拋出的異常不能直接捕獲,因為調用者將無法獲取到異常。建議使用Future或CompletableFuture來捕獲異步方法的異常并進行處理。
@Service
public class MyService {
@Async
public CompletableFuture<String> asyncMethod() {
try {
// 異步方法邏輯...
return CompletableFuture.completedFuture("Success");
} catch (Exception e) {
// 處理異常...
return CompletableFuture.failedFuture(e);
}
}
}
// 調用異步方法并處理異常
CompletableFuture<String> future = myService.asyncMethod();
future.exceptionally(ex -> {
// 異常處理邏輯...
return "Error";
});6、異步方法無返回結果
異步方法默認情況下是沒有返回值的,如果需要獲取異步方法的執(zhí)行結果,依然要使用Future或CompletableFuture,可以將其設置為返回類型。
@Service
public class MyService {
@Async
public CompletableFuture<String> asyncMethod() {
// 異步方法邏輯...
return CompletableFuture.completedFuture("Result");
}
}
// 調用異步方法并獲取結果
CompletableFuture<String> future = myService.asyncMethod();
String result = future.get(); // 阻塞等待結果當然,正常情況下我們不需要返回結果,而且我也不建議這么干,異步線程本身也最適合處理不需要返回值的一類任務。
7、循環(huán)調用問題
當在同一個類中調用異步方法時,注意避免出現(xiàn)無限遞歸的循環(huán)調用。這可能會導致應用程序卡死或內存溢出。
@Service
public class MyService {
@Autowired
private MyService myService; // 自身依賴
@Async
public void asyncMethod() {
// 異步方法邏輯...
myService.asyncMethod(); // 會導致無限遞歸調用
}
}這個坑點一般人不會遇到,但如果某些業(yè)務場景是關于樹形結構的遍歷、圖算法等等,還是有幾率出現(xiàn)這種情況的,這個坑點列出來僅供學習和了解。
8、異步方法順序問題
異步方法的執(zhí)行是非阻塞的,它們可能以任意順序完成。如果需要按照特定的順序處理結果,可以使用CompletableFuture的thenApply方法或者使用@Async的order屬性來指定順序。
@Service
public class MyService {
@Async("threadPoolTaskExecutor")
public CompletableFuture<String> asyncMethod1() {
// 異步方法1邏輯...
return CompletableFuture.completedFuture("Result1");
}
@Async("threadPoolTaskExecutor")
public CompletableFuture<String> asyncMethod2() {
// 異步方法2邏輯...
return CompletableFuture.completedFuture("Result2");
}
}
// 調用異步方法并處理結果順序
CompletableFuture<String> future1 = myService.asyncMethod1();
CompletableFuture<String> future2 = future1.thenCompose(
result1 -> myService.asyncMethod2());
String finalResult = future2.get(); // 阻塞等待最終結果總結
這里面,我個人認為絕大多數(shù)人會遇到的坑點集中在沒有配置自定義線程池、異步方法在同一個類中調用、事務不起作用這幾個問題上。
所以,萬金油的寫法還是專門定義一個AsyncService,將異步方法都寫在里面,需要使用的時候,就在其他類將其注入即可。
以上就是SpringBoot使用@Async注解可能會遇到的8大坑點匯總的詳細內容,更多關于SpringBoot @Async注解坑點的資料請關注腳本之家其它相關文章!
相關文章
java中public class與class的區(qū)別詳解
以下是對java中public class與class的區(qū)別進行了分析介紹,需要的朋友可以過來參考下2013-07-07

