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

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

使用前:

 使用后:

上代码:

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

@Override
    public Result searchDeviceList(HttpServletRequest httpRequest, DeviceQuery deviceQuery) {
        String cookie = httpRequest.getHeader("Cookie");

        List<DeviceQueryResponseVo> jsonList = new ArrayList<DeviceQueryResponseVo>();
        List<CabinetVo> cabinetVoList = new ArrayList<>();

        Map<String, CabinetVo> cabinetMap = new HashMap<>();
        Map<String, RoomCabinet> roomCabinetMap = new HashMap<>();
        Map<String, Object> result = new HashMap<>();
        try {
            //todo...

            if (cabinetCount > 0) {
                cabinetVoList = getCabinetList(cookie, CmdbConstants.CMDB_POST_CABINET_PAGE_URL, cabinetCount, cabinetVoList);

                for (int i = 0; i < cabinetVoList.size(); i++) {
                    String cabinetId = cabinetVoList.get(i).getBkInstId();
                    cabinetMap.put(cabinetId, cabinetVoList.get(i));
                    //查询机柜-机房
                    List<RoomVo> cabinetRoomVoList = new ArrayList<>();
                    cabinetRoomVoList = geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, cabinetRoomVoList, 1, Integer.parseInt(cabinetId));
                    String roomId = null;
                    if (CollectionUtils.isNotEmpty(cabinetRoomVoList)) {
                        roomId = cabinetRoomVoList.get(0).getBkInstId();
                    }
                    //查询机柜-设备
                    List<RoomVo> cabinetDeviceVoList = new ArrayList<>();
                    cabinetDeviceVoList = geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, cabinetDeviceVoList, 2, Integer.parseInt(cabinetId));
                    for (RoomVo roomVo : cabinetDeviceVoList) {
                        RoomCabinet roomCabinet = new RoomCabinet();
                        roomCabinet.setRoomId(roomId).setCabinetId(cabinetId);
                        roomCabinetMap.put(roomVo.getBkAsstInstId().toString(), roomCabinet);
                    }
                }
            } else {
                result.put("list", new ArrayList<DeviceQueryResponseVo>());
                result.put("total", 0);
                return Result.OK(result);
            }
            
	//todo...
            return Result.OK(result);
        } catch (InterruptedException e) {
            log.error("查询线程异常 !");
            return Result.error(999, "查询失败,Cookie失效!");
        } catch (BaseException e) {
            return Result.error(999, e.getMsg());
        } catch (Exception e) {
            return Result.error(999, "查询失败,Cookie失效!");
        }
    }

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

@Override
    public Result searchDeviceList(HttpServletRequest httpRequest, DeviceQuery deviceQuery) {
        String cookie = httpRequest.getHeader("Cookie");
      
        List<DeviceQueryResponseVo> jsonList = new ArrayList<DeviceQueryResponseVo>();
        List<CabinetVo> cabinetVoList = new ArrayList<>();

        Map<String, CabinetVo> cabinetMap = new HashMap<>();
        Map<String, RoomCabinet> roomCabinetMap = new HashMap<>();
        Map<String, Object> result = new HashMap<>();
        try {
          //todo...
            int cabinetCount = getCount(cookie, CmdbConstants.CMDB_POST_CABINET_COUNT_URL);
            CountDownLatch latch = new CountDownLatch(0);
            if (cabinetCount > 0) {
                cabinetVoList = getCabinetList(cookie, CmdbConstants.CMDB_POST_CABINET_PAGE_URL, cabinetCount, cabinetVoList);

                latch = new CountDownLatch(cabinetVoList.size());

                for (int i = 0; i < cabinetVoList.size(); i++) {
                    // 提交任务给线程池处理
                    executorConfig.asyncServiceExecutor().execute(new CabinetTask(cabinetVoList.get(i), cookie, cabinetMap, roomCabinetMap, latch,this));
                }
            } else {
                result.put("list", new ArrayList<DeviceQueryResponseVo>());
                result.put("total", 0);
                return Result.OK(result);
            }
            // 等待所有任务完成
            latch.await();
	//todo...
            return Result.OK(result);
        } catch (InterruptedException e) {
            log.error("查询线程异常 !");
            return Result.error(999, "查询失败,Cookie失效!");
        } catch (BaseException e) {
            return Result.error(999, e.getMsg());
        } catch (Exception e) {
            return Result.error(999, "查询失败,Cookie失效!");
        }
    }

线程执行部分:

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

public class CabinetTask implements Runnable {
    private DeviceServiceImpl deviceService;
    private CabinetVo cabinetVo;
    private String cookie;
    private Map<String, CabinetVo> cabinetMap;
    private Map<String, RoomCabinet> roomCabinetMap;
    private CountDownLatch latch;

    public CabinetTask(CabinetVo cabinetVo, String cookie, Map<String, CabinetVo> cabinetMap,
                       Map<String, RoomCabinet> roomCabinetMap, CountDownLatch latch, DeviceServiceImpl deviceService) {
        this.cabinetVo = cabinetVo;
        this.cookie = cookie;
        this.cabinetMap = cabinetMap;
        this.roomCabinetMap = roomCabinetMap;
        this.latch = latch;
        this.deviceService = deviceService;
    }

    @Override
    public void run() {
        String cabinetId = cabinetVo.getBkInstId();
        cabinetMap.put(cabinetId, cabinetVo);

        //查询机柜-机房
        List<RoomVo> cabinetRoomVoList = new ArrayList<>();
        cabinetRoomVoList = deviceService.geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, cabinetRoomVoList, 1, Integer.parseInt(cabinetId));
        String roomId = null;
        if (CollectionUtils.isNotEmpty(cabinetRoomVoList)) {
            roomId = cabinetRoomVoList.get(0).getBkInstId();
        }

        //查询机柜-设备
        List<RoomVo> cabinetDeviceVoList = new ArrayList<>();
        cabinetDeviceVoList = deviceService.geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, new ArrayList<>(), 2, Integer.parseInt(cabinetVo.getBkInstId()));

        // 对 cabinetDeviceVoList 进行后续处理
        for (RoomVo roomVo : cabinetDeviceVoList) {
            RoomCabinet roomCabinet = new RoomCabinet();
            roomCabinet.setRoomId(roomId).setCabinetId(cabinetId);
            roomCabinetMap.put(roomVo.getBkAsstInstId().toString(), roomCabinet);
        }

        // 任务完成,减少任务计数
        latch.countDown();
    }
}

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1073513.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高并发 发送请求(asyncio)

在接手这个项目之前&#xff0c;关于数据存储的代码逻辑如上图&#xff0c;看起来按部就班&#xff0c;也很合理。&#xff08;本人觉得这就像个玩具车&#xff09; 在最后一步发送HTTP request响应足够快的话&#xff0c;其实速度说不上快但稳定&#xff0c;可以接受。但偏偏…

segment方案解决VXLAN分布式网关DCI间互联

segment概念&#xff1a; segment方案是在需要互联的两个DCI间建立3条VXLAN隧道实现两个DCI间的二层和三层间互通需求&#xff0c;常用于大型的DCI间互联&#xff0c;无需考虑两个DCI内的VXLAN参数规划的不同&#xff0c;其中二层互通可以采用映射VNI或局部VNI的方式进行解决&…

运营商大数据,三网融合大数据,联通大数据,移动大数据

有许多公司和企业依靠电话营销和短信营销。对于他们来说&#xff0c;客户资源就是维生素和维生素&#xff0c;客户资源的及时性和准确性是这些公司和企业最关心的问题。长期使用低质量、大量无效的客户资源&#xff0c;是对时间的浪费&#xff0c;是对人力物力财力的浪费&#…

基于Springboot实现房屋租赁租房平台系统项目【项目源码+论文说明】

基于Springboot实现房屋租赁租房平台系统演示 摘要 在网络高速发展的时代&#xff0c;众多的软件被开发出来&#xff0c;给用户带来了很大的选择余地&#xff0c;而且人们越来越追求更个性的需求。在这种时代背景下&#xff0c;房东只能以用户为导向&#xff0c;所以开发租房网…

基于springboot实现准妈妈孕期交流平台项目【项目源码+论文说明】分享

基于springboot实现准妈妈孕期交流平台演示 摘要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;准妈妈孕期交流平台当然也不能排除在外。准妈妈孕期交流平台是以实际运用为开…

加密的重要性,MySQL加密有哪些好处?

加密是一种将信息转化为无法直接读取的格式的技术&#xff0c;从而保护信息安全。在当今数字化的世界中&#xff0c;数据已成为企业的重要资产&#xff0c;因此加密的重要性不言而喻。在这篇文章中&#xff0c;我们将探讨MySQL加密的好处以及如何选择合适的加密算法。 MySQL加密…

Windows系统安装

安装Windows系统有很多方法、而Windows系统也有不同的版本&#xff0c;下面主要介绍两种方法安装系统&#xff0c;第一种是使用微软官方提供的镜像文件安装Win10系统&#xff0c;第二种是使用微PE工具箱来安装Win10系统 准备工作&#xff1a;内存大于8G的空U盘&#xff0c;Win1…

软件测试「转行」答疑(未完更新中)

⭐ 专栏简介 软件测试行业「转行」答疑&#xff1a; 如果你对于互联网的职业了解一知半解&#xff01;不知道行业的前景如何&#xff1f;对于众说纷纭的引流博主说法不知所措&#xff01;不确定这个行业到底适不适合自己&#xff1f; 那么这一篇文章可以告诉你所有真实答案&a…

10-Node.js入门

01.什么是 Node.js 目标 什么是 Node.js&#xff0c;有什么用&#xff0c;为何能独立执行 JS 代码&#xff0c;演示安装和执行 JS 文件内代码 讲解 Node.js 是一个独立的 JavaScript 运行环境&#xff0c;能独立执行 JS 代码&#xff0c;因为这个特点&#xff0c;它可以用来…

使用docker搭建nacos单机、集群 + mysql

单机搭建 1 拉取mysql镜像 docker pull mysql:5.7.40 2 启动mysql容器 docker run -d --namemysql-server -p 3306:3306 -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD123456 mysql:5.7.40 3 执行nacos的数据库脚本 /* * Copyright 1999-2018 Alibaba Group Holding L…

树的基本概念及二叉树

目录 一、树的基本概念 &#xff08;1&#xff09;树的结点 &#xff08;2&#xff09;度 &#xff08;3&#xff09;结点层次 &#xff08;4&#xff09;树的高度 树的特点&#xff1a; 二、二叉树 &#xff08;1&#xff09;满二叉树 &#xff08;2&#xff09;完…

nodejs 16版本

Index of /download/release/latest-v16.x/

医院内网多台主机中毒流量分析案例

背景 最近医院的医生多次反馈网络出现慢和卡顿现象。医院十分重视这个问题&#xff0c;并将之反馈给网络部门同事进行处理。经过多次排查和分析&#xff0c;并没有发现网络中的异常情况。为了更好地解决这一问题&#xff0c;我们推荐安装NetInside流量分析系统。这个系统可以对…

c++视觉图像----扩充边界

图像扩充边界 #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp>int main() {// 读取图像cv::Mat image cv::imread("1.jpg", cv::IMREAD_COLOR);if (image.empty()) {std::cerr << "Could not open or find the imag…

【JVM--StringTable字符串常量池】

文章目录 1. String 的基本特性2. 字符串拼接操作3. intern()的使用4. StringTable 的垃圾回收 1. String 的基本特性 String 声明为 final 的&#xff0c;不可被继承String 实现了 Serializable 接口&#xff1a;表示字符串是支持序列化的。String 实现了 Comparable 接口&am…

求臻人故事 | 在求臻医学的沃土中,我像竹子般茁壮成长

在这个快节奏的社会中&#xff0c;我们时常忽略了身边的“小人物”&#xff0c;他们或许默默无闻&#xff0c;或许平凡无奇&#xff0c;但他们的经历、奋斗和成就&#xff0c;却能给我们带来深深的启示。让我们一起走进每个平凡的求臻人世界&#xff0c;聆听他们的“大故事”&a…

Direct3D网格(一)

创建网格 我们可以用D3DXCreateMeshFVF函数创建一个"空"网格对象 &#xff0c;空网格对象是指我们指定了网格的面片总数和顶点总数&#xff0c;然后由该函数为顶点缓存、索引缓存和属性缓存分配大小合适的内存&#xff0c;之后即可手工填入网格数据。 HRESULT WINA…

供水管网监测系统

随着城市人口的不断增长和经济的快速发展&#xff0c;供水管网的安全和可靠性变得尤为重要。在过去&#xff0c;供水管网的监测往往是依靠人工巡查&#xff0c;这种方式不仅费时费力&#xff0c;而且容易出现疏漏和盲区。然而&#xff0c;随着科技的进步&#xff0c;供水管网监…

【算法|动态规划No.16】leetcode931. 下降路径最小和

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

智能售后工单系统是什么?智能工单系统有什么用?

对于传统的客服问题处理机制中&#xff0c;如果使用智能工单详细记录客户的问题以及解决问题的全过程&#xff0c;可以有效地帮助客服中心或业务管理层从总体层面了解客户的问题&#xff0c;给出有效的解决方案以及处理问题的紧急程度。从每个服务分支到问题&#xff0c;基于大…