记一次CountDownLatch在SpringBoot中配合@Async使用

需求

项目使用springboot,有一个场景需要先从本地查询所有数据,然后再调用第三方接口填充其他字段,每次调用第三方接口都需要本地数据的字段作为查询条件。厂商提供的接口只能单个查询,所以只能遍历从本地查询的数据然后挨个调用接口,这样响应时间实在慢且效率太低。

那就想办法优化呗,第一想法肯定是启用多线程,让每一条从本地数据库查询的记录可以并行调用第三方接口。

首先新建一个线程任务类来调用第三方接口并填充数据,用spring的@Async注解实现异步调用,伪代码如下:

@Component
public class AsyncTask {


    /**
     * 异步调用第三方接口查询
     */
    @Async
    public void queryTask(Entity entity){
       Data data = doPost();
       entity.setData(data);
    }
   
}

Service层循环调用

public class Service {
    
    @Autowired
    private AsyncTask asyncTask;
    @Autowired
    private EntityMapper mapper;
    
    public List<Entity> queryData(){
        
        List<Entity> list = mapper.selectAll();
        for(Entity entity:list){
            asyncTask.queryTask(entity);
        }
        
       return list;
    }
}

这样就实现了异步请求接口,效率上提升了很多。但是,由于异步调用的原因,数据还没填充完就会返回,这显然不是我们想要的效果。我们必须等待AsyncTask中的所有线程结束后,再返回当前调用线程任务的方法。于是就想到了JDK1.5版本后提供的计数器CountDownLatch(至于CountDownLatch的用法本文不阐述,只是第一次使用记录一下,有错误的地方还希望大家给建议)。

思路:

在Service层的方法中实例化CountDownLatch并且制定线程个数,线程个数就是从本地数据库查询的list的长度,并且传入线程任务中,每个线程执行完毕就调用countDown()方法。最后在Service层中调用await()方法。这样在线程计数为零之前,Service的线程就会一直等待。

Service:

public class Service {
    
    @Autowired
    private AsyncTask asyncTask;
    @Autowired
    private EntityMapper mapper;
    
    public List<Entity> queryData(){
        
        List<Entity> list = mapper.selectAll();
        CountDownLatch latch = new CountDownLatch(list.size());
        for(Entity entity:list){
            asyncTask.queryTask(entity,latch);
        }
       latch.await();
       return list;
    }
}

AsyncTask:

@Component
public class AsyncTask {


    /**
     * 异步调用第三方接口查询
     */
    @Async
    public void queryTask(Entity entity,CountDownLatch latch){
       Data data = doPost();
       entity.setData(data);
       latch.countDown();
    }
   
}

至此问题解决。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值