• 使用CountDownLatch解决接口循环网络请求造成的耗时问题


    背景:由于查询接口调用第三方平台,需要通过http请求获得设备数据,但由于第三方接口获取数据的限制,只能通过某些接口获取机柜与机房、机柜与设备关系后再查询对应设备的信息,单线程执行效果慢造成了网络io耗时较长的问题,后引入CountDownLatch计数器来解决。
    接口的响应时间

    使用前:

     使用后:

    上代码:

    原来的代码(主要列出耗时代码块):

    1. @Override
    2. public Result searchDeviceList(HttpServletRequest httpRequest, DeviceQuery deviceQuery) {
    3. String cookie = httpRequest.getHeader("Cookie");
    4. List jsonList = new ArrayList();
    5. List cabinetVoList = new ArrayList<>();
    6. Map cabinetMap = new HashMap<>();
    7. Map roomCabinetMap = new HashMap<>();
    8. Map result = new HashMap<>();
    9. try {
    10. //todo...
    11. if (cabinetCount > 0) {
    12. cabinetVoList = getCabinetList(cookie, CmdbConstants.CMDB_POST_CABINET_PAGE_URL, cabinetCount, cabinetVoList);
    13. for (int i = 0; i < cabinetVoList.size(); i++) {
    14. String cabinetId = cabinetVoList.get(i).getBkInstId();
    15. cabinetMap.put(cabinetId, cabinetVoList.get(i));
    16. //查询机柜-机房
    17. List cabinetRoomVoList = new ArrayList<>();
    18. cabinetRoomVoList = geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, cabinetRoomVoList, 1, Integer.parseInt(cabinetId));
    19. String roomId = null;
    20. if (CollectionUtils.isNotEmpty(cabinetRoomVoList)) {
    21. roomId = cabinetRoomVoList.get(0).getBkInstId();
    22. }
    23. //查询机柜-设备
    24. List cabinetDeviceVoList = new ArrayList<>();
    25. cabinetDeviceVoList = geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, cabinetDeviceVoList, 2, Integer.parseInt(cabinetId));
    26. for (RoomVo roomVo : cabinetDeviceVoList) {
    27. RoomCabinet roomCabinet = new RoomCabinet();
    28. roomCabinet.setRoomId(roomId).setCabinetId(cabinetId);
    29. roomCabinetMap.put(roomVo.getBkAsstInstId().toString(), roomCabinet);
    30. }
    31. }
    32. } else {
    33. result.put("list", new ArrayList());
    34. result.put("total", 0);
    35. return Result.OK(result);
    36. }
    37. //todo...
    38. return Result.OK(result);
    39. } catch (InterruptedException e) {
    40. log.error("查询线程异常 !");
    41. return Result.error(999, "查询失败,Cookie失效!");
    42. } catch (BaseException e) {
    43. return Result.error(999, e.getMsg());
    44. } catch (Exception e) {
    45. return Result.error(999, "查询失败,Cookie失效!");
    46. }
    47. }

    使用CountDownLatch后,查询接口部分:

    1. @Override
    2. public Result searchDeviceList(HttpServletRequest httpRequest, DeviceQuery deviceQuery) {
    3. String cookie = httpRequest.getHeader("Cookie");
    4. List jsonList = new ArrayList();
    5. List cabinetVoList = new ArrayList<>();
    6. Map cabinetMap = new HashMap<>();
    7. Map roomCabinetMap = new HashMap<>();
    8. Map result = new HashMap<>();
    9. try {
    10. //todo...
    11. int cabinetCount = getCount(cookie, CmdbConstants.CMDB_POST_CABINET_COUNT_URL);
    12. CountDownLatch latch = new CountDownLatch(0);
    13. if (cabinetCount > 0) {
    14. cabinetVoList = getCabinetList(cookie, CmdbConstants.CMDB_POST_CABINET_PAGE_URL, cabinetCount, cabinetVoList);
    15. latch = new CountDownLatch(cabinetVoList.size());
    16. for (int i = 0; i < cabinetVoList.size(); i++) {
    17. // 提交任务给线程池处理
    18. executorConfig.asyncServiceExecutor().execute(new CabinetTask(cabinetVoList.get(i), cookie, cabinetMap, roomCabinetMap, latch,this));
    19. }
    20. } else {
    21. result.put("list", new ArrayList());
    22. result.put("total", 0);
    23. return Result.OK(result);
    24. }
    25. // 等待所有任务完成
    26. latch.await();
    27. //todo...
    28. return Result.OK(result);
    29. } catch (InterruptedException e) {
    30. log.error("查询线程异常 !");
    31. return Result.error(999, "查询失败,Cookie失效!");
    32. } catch (BaseException e) {
    33. return Result.error(999, e.getMsg());
    34. } catch (Exception e) {
    35. return Result.error(999, "查询失败,Cookie失效!");
    36. }
    37. }

    线程执行部分:

    1. import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
    2. import java.util.ArrayList;
    3. import java.util.List;
    4. import java.util.Map;
    5. import java.util.concurrent.CountDownLatch;
    6. public class CabinetTask implements Runnable {
    7. private DeviceServiceImpl deviceService;
    8. private CabinetVo cabinetVo;
    9. private String cookie;
    10. private Map cabinetMap;
    11. private Map roomCabinetMap;
    12. private CountDownLatch latch;
    13. public CabinetTask(CabinetVo cabinetVo, String cookie, Map cabinetMap,
    14. Map roomCabinetMap, CountDownLatch latch, DeviceServiceImpl deviceService) {
    15. this.cabinetVo = cabinetVo;
    16. this.cookie = cookie;
    17. this.cabinetMap = cabinetMap;
    18. this.roomCabinetMap = roomCabinetMap;
    19. this.latch = latch;
    20. this.deviceService = deviceService;
    21. }
    22. @Override
    23. public void run() {
    24. String cabinetId = cabinetVo.getBkInstId();
    25. cabinetMap.put(cabinetId, cabinetVo);
    26. //查询机柜-机房
    27. List cabinetRoomVoList = new ArrayList<>();
    28. cabinetRoomVoList = deviceService.geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, cabinetRoomVoList, 1, Integer.parseInt(cabinetId));
    29. String roomId = null;
    30. if (CollectionUtils.isNotEmpty(cabinetRoomVoList)) {
    31. roomId = cabinetRoomVoList.get(0).getBkInstId();
    32. }
    33. //查询机柜-设备
    34. List cabinetDeviceVoList = new ArrayList<>();
    35. cabinetDeviceVoList = deviceService.geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, new ArrayList<>(), 2, Integer.parseInt(cabinetVo.getBkInstId()));
    36. // 对 cabinetDeviceVoList 进行后续处理
    37. for (RoomVo roomVo : cabinetDeviceVoList) {
    38. RoomCabinet roomCabinet = new RoomCabinet();
    39. roomCabinet.setRoomId(roomId).setCabinetId(cabinetId);
    40. roomCabinetMap.put(roomVo.getBkAsstInstId().toString(), roomCabinet);
    41. }
    42. // 任务完成,减少任务计数
    43. latch.countDown();
    44. }
    45. }

     

     

     

  • 相关阅读:
    iOS 列表页面实时刷新解决方案
    vue页面添加水印(可用于H5,APP)
    华为云CodeArts Check代码检查服务用户声音反馈集锦(1)
    Redis与分布式-哨兵模式
    驱动开发,IO多路复用实现过程,epoll方式
    待抓取位姿转换到世界坐标系下
    [Tools: cntk] Linux下cntk-gpu安装
    单例设计模式常见的七种写法
    聚类算法学习笔记(一)
    unity 改变模型及其子物体的Shader和透明度
  • 原文地址:https://blog.csdn.net/qq_43511677/article/details/133707594