java多线程中ArrayList应当替换为CopyOnWriteArrayList
@ApiOperation(value = "获取子公司sub,省分prov,总部hq, 全部 total 指标值中的 最高分,最低分,平均分") @RequestMapping(value = "/getMaxAndMinAndAverageKpiValue", method = RequestMethod.POST) private Map<String, Object> getMaxAndMinAndAverageKpiValue(@RequestBody KpiStatisticsReq req) { if (req.getKpiIds() == null) { return ResponseUtil.fail("请输入 kpi指标的kpiId数组"); } try { List<HashMap<String, Object>> list = new CopyOnWriteArrayList(); if (req.getBranch() == null) { req.setBranch("total"); } List<String> ldapOrgCodesList1 = soaOrgWithPathBranchServiceImpl.queryLdapOrgCodesByBranch(req.getBranch()); List<String> ldapOrgCodesList2= new ArrayList<>(); ldapOrgCodesList2.addAll(ldapOrgCodesList1); if (req.getLdapOrgCodes()!=null){ ldapOrgCodesList2.addAll(Arrays.asList(req.getLdapOrgCodes())); } final List<String> ldapOrgCodesList=ldapOrgCodesList2.stream().distinct().collect(Collectors.toList()); ForkJoinPool forkJoinPool = new ForkJoinPool(); for (Integer kpiId : req.getKpiIds()) { forkJoinPool.execute(() -> { Kpi kpi = kpiServiceImpl.queryInfoByNatrualKey(kpiId); // 获取 子公司编码 ldap code HashMap<String, Object> datas = new HashMap<>(); datas.put("kpi", kpi); // List<KpiValue> appKpiListAll = new ArrayList<>(); List<Double> doubles = new ArrayList<>(); KpiValue appKpiParam = new KpiValue(); for (String scope : ldapOrgCodesList) { appKpiParam.setScope(scope); appKpiParam.setKpiId(kpiId); // List<KpiValue> appKpiList = kpiValueService.searchInfos(appKpiParam); KpiValue kpiValue = kpiValueService.searchOne(appKpiParam); if (kpiValue != null && kpiValue.getValue() != null && !kpiValue.getValue().trim().equals("")) { // doubles.add(Double.parseDouble(kpiValue.getValue())); doubles.add(new BigDecimal(kpiValue.getValue()).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } } if (doubles.size() > 0) { DoubleSummaryStatistics statistics = doubles.stream().mapToDouble(x -> x).summaryStatistics(); datas.put("max", BigDecimal.valueOf(statistics.getMax()).setScale(4, BigDecimal.ROUND_HALF_UP)); datas.put("min", BigDecimal.valueOf(statistics.getMin()).setScale(4, BigDecimal.ROUND_HALF_UP)); datas.put("average", BigDecimal.valueOf(statistics.getAverage()).setScale(4, BigDecimal.ROUND_HALF_UP)); datas.put("sum", BigDecimal.valueOf(statistics.getSum()).setScale(4, BigDecimal.ROUND_HALF_UP)); datas.put("count", statistics.getCount()); } list.add(datas); }); } while (forkJoinPool.getActiveThreadCount() != 0) { Thread.sleep(100); } forkJoinPool.shutdown(); return ResponseUtil.ok(list); } catch (Exception e) { e.printStackTrace(); LoggerUtils.error(getClass(), "查询失败!" + e.getMessage()); return ResponseUtil.fail("查询失败!" + e.getMessage()); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~