CountDownLatch在SpringBoot中配合@Async使用


需求

項目使用springboot,有一個場景需要先從本地查詢所有數據,然后再調用第三方接口填充其他字段,每次調用第三方接口都需要本地數據的字段作為查詢條件。廠商提供的接口只能單個查詢,所以只能遍歷從本地查詢的數據然后挨個調用接口,這樣響應時間實在慢且效率太低。

那就想辦法優化唄,第一想法肯定是啟用多線程,讓每一條從本地數據庫查詢的記錄可以並行調用第三方接口。

首先新建一個線程任務類來調用第三方接口並填充數據,用spring的@Async注解實現異步調用,偽代碼如下:


   
   
  
  
          
  1. @Component
  2. public class AsyncTask {
  3. /**
  4. * 異步調用第三方接口查詢
  5. */
  6. @Async
  7. public void queryTask(Entity entity){
  8. Data data = doPost();
  9. entity.setData(data);
  10. }
  11. }

Service層循環調用


   
   
  
  
          
  1. public class Service {
  2. @Autowired
  3. private AsyncTask asyncTask;
  4. @Autowired
  5. private EntityMapper mapper;
  6. public List<Entity> queryData(){
  7. List<Entity> list = mapper.selectAll();
  8. for(Entity entity:list){
  9. asyncTask.queryTask(entity);
  10. }
  11. return list;
  12. }
  13. }

這樣就實現了異步請求接口,效率上提升了很多。但是,由於異步調用的原因,數據還沒填充完就會返回,這顯然不是我們想要的效果。我們必須等待AsyncTask中的所有線程結束后,再返回當前調用線程任務的方法。於是就想到了JDK1.5版本后提供的計數器CountDownLatch(至於CountDownLatch的用法本文不闡述,只是第一次使用記錄一下,有錯誤的地方還希望大家給建議)。

思路:

在Service層的方法中實例化CountDownLatch並且制定線程個數,線程個數就是從本地數據庫查詢的list的長度,並且傳入線程任務中,每個線程執行完畢就調用countDown()方法。最后在Service層中調用await()方法。這樣在線程計數為零之前,Service的線程就會一直等待。

Service:


   
   
  
  
          
  1. public class Service {
  2. @Autowired
  3. private AsyncTask asyncTask;
  4. @Autowired
  5. private EntityMapper mapper;
  6. public List<Entity> queryData(){
  7. List<Entity> list = mapper.selectAll();
  8. CountDownLatch latch = new CountDownLatch(list.size());
  9. for(Entity entity:list){
  10. asyncTask.queryTask(entity,latch);
  11. }
  12. latch.await();
  13. return list;
  14. }
  15. }

AsyncTask:


   
   
  
  
          
  1. @Component
  2. public class AsyncTask {
  3. /**
  4. * 異步調用第三方接口查詢
  5. */
  6. @Async
  7. public void queryTask(Entity entity,CountDownLatch latch){
  8. Data data = doPost();
  9. entity.setData(data);
  10. latch.countDown();
  11. }
  12. }

至此問題解決。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM