前几天有个需求让导出物流的发货信息, 比如2023年1月1日之后的
sql查了下数据量比较大, 而且需要sql查询到的数据中的一些参数, 调用外部api接口才能获取到完成的数据
由于外部api只能依次调用, 每次只能查询一条数据, 导致excel的导出非常缓慢, 最后考虑使用多线程异步查询外部api, 汇总数据, 最后做excel导出
考虑到需要做数据汇总, 使用CountDownLatch最合适
CountDownLatch可以使一个获多个线程等待其他线程各自执行完毕后再执行。
CountDownLatch 定义了一个计数器,和一个阻塞队列, 当计数器的值递减为0之前,阻塞队列里面的线程处于挂起状态,当计数器递减到0时会唤醒阻塞队列所有线程,这里的计数器是一个标志,可以表示一个任务一个线程,也可以表示一个倒计时器,CountDownLatch可以解决那些一个或者多个线程在执行之前必须依赖于某些必要的前提业务先执行的场景。
1. 首先查询要统计的物流信息
Lists.partition 是 guava 提供的工具类, 目的在于把一个很长的集合, 拆分多多个小集合, 比如我这里是把 itemList 做拆分, 每一个小集合的长度是 50, 之后 创建一个拥有 50 个计数器的 CountDownLatch, 计数器的数量一定要是拆分后集合的数量, 不然会丢数据
2. 多线程执行
循环外层集合, 会循环50次, 每一次循环取到里面的小集合, 也就是真正要处理的业务数据, 然后开启一个线程调用第三方api接口, 每一个小集合处理完毕, 千万要记住在 finally 里把 计数器做 减一操作
3. 等待所有线程执行完毕
使用 countDownLatch的 await() 方法, 等待所有线程执行完毕, 也就是 计数器 为0, 从源码的角度看就是 state 这个字段是不是0, 如果不放心, 可以传递等待超时时间
4. excel导出
等所有线程执行完毕, 做excel导出工作