java利用多线程,线程池加快任务处理时间,等待所有线程结束,数据统一处理

遇到了业务上处理很慢的情况,都可以用多线程解决,这是原先未优化的代码

/*** 导出excel*/@GetMapping("/export/excel")@ApiOperationSupport(order = 11)@ApiOperation(value = "导出excel", notes = "传入gaugeRecord")public void exportExcel(GaugeRecordEntity gaugeRecord, HttpServletResponse response) throws IOException {GaugeTestEntity testCondition = new GaugeTestEntity();testCondition.setBatchId(gaugeRecord.getBatchId());
//		testCondition.setSiteCode(gaugeRecord.getSiteCode());// 查询所有人的基本信息List<TesterEntity> allTesters = testerService.list();
// 将所有人的信息转换为 id 和 entity 的 HashMapMap<String, TesterEntity> testerMap = allTesters.stream().collect(Collectors.toMap(TesterEntity::getIdNo, Function.identity()));List<GaugeTestEntity> gauges = gaugeTestService.selectEffectiveGauge(testCondition);List<GaugeTestExcel> excels = gauges.stream().map(g -> {TesterEntity tester = testerMap.get(g.getUserId());GaugeTestExcel e = new GaugeTestExcel();e.setUserId(g.getUserId());e.setUserName(g.getUserName());e.setTestTime(g.getTestTime());e.setGender(CommonUtil.getGender(g.getUserId())==1?"男":"女");e.setBirthday(CommonUtil.getBirthday(g.getUserId()));
//			e.setBirthdayText(e.getBirthday()==null?"":e.getBirthday().format(DateTimeFormatter.ofPattern("yyyyMMdd")));if (tester != null) {e.setEducationText(DictBizCache.getValue(DictBizEnum.EDUCATION, tester.getEducation()));e.setEducationYears(tester.getEducationYears());e.setIsOnlychildText(DictBizCache.getValue(DictBizEnum.ONLY_CHILD, tester.getIsOnlychild()));if (!DictBizCache.getValue(DictBizEnum.ONLY_CHILD, tester.getIsOnlychild()).equals("独生子女")) {e.setChildrenQty(tester.getChildrenQty());e.setChildrenRanking(tester.getChildrenRanking());}e.setSubjectiveSes(tester.getSubjectiveSes());e.setFamilyMonthlyEarningText(DictBizCache.getValue(DictBizEnum.FAMILY_MONTHLY_EARNING, tester.getFamilyMonthlyEarning()));e.setEducationMotherText(DictBizCache.getValue(DictBizEnum.PARENT_EDUCATION, tester.getEducationMother()));e.setEducationFantherText(DictBizCache.getValue(DictBizEnum.PARENT_EDUCATION, tester.getEducationFanther()));}JSONObject statistical = JSON.parseObject(g.getStatistical());e.setTaiyin(statistical.get("太阴人格") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("太阴人格").toString()));e.setYanjinxing(statistical.get("严谨性人格") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("严谨性人格").toString()));e.setShenjingzhi(statistical.get("神经质人格") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("神经质人格").toString()));e.setRengetezhi(statistical.get("人格特质") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("人格特质").toString()));e.setTezhijiaolv(statistical.get("特质焦虑") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("特质焦虑").toString()));e.setShenghuomanyidu(statistical.get("生活满意度") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("生活满意度").toString()));e.setShengmingyiyigan(statistical.get("生命意义感") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("生命意义感").toString()));e.setZizun(statistical.get("自尊") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("自尊").toString()));e.setZhuguanxingfugan(statistical.get("主观幸福感") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("主观幸福感").toString()));e.setYalizhijue(statistical.get("压力知觉") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("压力知觉").toString()));e.setYiyu(statistical.get("抑郁") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("抑郁").toString()));e.setXinlijiankang(statistical.get("心理健康") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("心理健康").toString()));e.setJijiyingdui(statistical.get("积极应对") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("积极应对").toString()));e.setXiaojiyingdui(statistical.get("消极应对") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("消极应对").toString()));e.setQingxutiaojie(statistical.get("情绪调节") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("情绪调节").toString()));e.setXinlitanxing(statistical.get("心理弹性") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("心理弹性").toString()));e.setZiwoxiaonenggan(statistical.get("自我效能感") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("自我效能感").toString()));e.setYaliyingdui(statistical.get("压力应对") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("压力应对").toString()));e.setRenjiqinggan(statistical.get("人际情感") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("人际情感").toString()));e.setRenjichongtu(statistical.get("人际冲突") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("人际冲突").toString()));e.setQinshehui(statistical.get("亲社会倾向") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("亲社会倾向").toString()));e.setGongji(statistical.get("攻击") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("攻击").toString()));e.setRenjiguanxi(statistical.get("人际关系") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("人际关系").toString()));e.setShiyingnengli(statistical.get("适应能力") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("适应能力").toString()));JSONObject answer = JSON.parseObject(g.getUserAnswer());e.setQ1((String) answer.get("Q1"));e.setQ2((String) answer.get("Q2"));e.setQ3((String) answer.get("Q3"));e.setQ4((String) answer.get("Q4"));e.setQ5((String) answer.get("Q5"));e.setQ6((String) answer.get("Q6"));e.setQ7((String) answer.get("Q7"));e.setQ8((String) answer.get("Q8"));e.setQ9((String) answer.get("Q9"));e.setQ10((String) answer.get("Q10"));e.setQ11((String) answer.get("Q11"));e.setQ12((String) answer.get("Q12"));e.setQ13((String) answer.get("Q13"));e.setQ14((String) answer.get("Q14"));e.setQ15((String) answer.get("Q15"));e.setQ16((String) answer.get("Q16"));e.setQ17((String) answer.get("Q17"));e.setQ18((String) answer.get("Q18"));e.setQ19((String) answer.get("Q19"));e.setQ20((String) answer.get("Q20"));e.setQ21((String) answer.get("Q21"));e.setQ22((String) answer.get("Q22"));e.setQ23((String) answer.get("Q23"));e.setQ24((String) answer.get("Q24"));e.setQ25((String) answer.get("Q25"));e.setQ26((String) answer.get("Q26"));e.setQ27((String) answer.get("Q27"));e.setQ28((String) answer.get("Q28"));e.setQ29((String) answer.get("Q29"));e.setQ30((String) answer.get("Q30"));e.setQ31((String) answer.get("Q31"));e.setQ32((String) answer.get("Q32"));e.setQ33((String) answer.get("Q33"));e.setQ34((String) answer.get("Q34"));e.setQ35((String) answer.get("Q35"));e.setQ36((String) answer.get("Q36"));e.setQ37((String) answer.get("Q37"));e.setQ38((String) answer.get("Q38"));e.setQ39((String) answer.get("Q39"));e.setQ40((String) answer.get("Q40"));e.setQ41((String) answer.get("Q41"));e.setQ42((String) answer.get("Q42"));e.setQ43((String) answer.get("Q43"));e.setQ44((String) answer.get("Q44"));e.setQ45((String) answer.get("Q45"));e.setQ46((String) answer.get("Q46"));e.setQ47((String) answer.get("Q47"));e.setQ48((String) answer.get("Q48"));e.setQ49((String) answer.get("Q49"));e.setQ50((String) answer.get("Q50"));e.setQ51((String) answer.get("Q51"));e.setQ52((String) answer.get("Q52"));e.setQ53((String) answer.get("Q53"));e.setQ54((String) answer.get("Q54"));e.setQ55((String) answer.get("Q55"));e.setQ56((String) answer.get("Q56"));e.setQ57((String) answer.get("Q57"));e.setQ58((String) answer.get("Q58"));e.setQ59((String) answer.get("Q59"));return e;}).collect(Collectors.toList());//查询工作记忆任务List<GaugeTestEntity> gaugesGong = gaugeTestService.list(new QueryWrapper<GaugeTestEntity>().lambda().eq(GaugeTestEntity::getBatchId, gaugeRecord.getBatchId()).eq(GaugeTestEntity::getTestType, 1707));List<NBackTestExcel> nbackExcels = gaugesGong.stream().map(g -> {TesterEntity tester = testerService.selectByIdNo(g.getUserId());NBackTestExcel e = new NBackTestExcel();e.setUserId(g.getUserId());e.setUserName(g.getUserName());e.setTestTime(g.getTestTime());e.setGender(CommonUtil.getGender(g.getUserId())==1?"男":"女");e.setBirthday(CommonUtil.getBirthday(g.getUserId()));
//			e.setBirthdayText(e.getBirthday()==null?"":e.getBirthday().format(DateTimeFormatter.ofPattern("yyyyMMdd")));if (tester != null) {}//构建hashMap来存各个block的对象HashMap<Integer, List<NBlackJsonVO>> nbackListHashMap = new HashMap<>();ArrayList<NBlackJsonVO> nBlackJsonVOS = new ArrayList<>();//JSONArray jsonArrayNBack = JSON.parseArray(g.getUserAnswer());//一共160个for (int i = 0; i < jsonArrayNBack.size(); i++) {JSONObject jsonObject = jsonArrayNBack.getJSONObject(i);String SDTTask1 = jsonObject.getString("SDTTask1");//任务一的信号检测论指标:1击中(应该按左键,被试按了左键: targetTask1=1 & respLeft=1),2漏报(应该按左键,被试没按左键:targetTask1=1 & respLeft = 0),3正确拒斥(无需按左键,被试没按左键:targetTask1=0 & respLeft =0),4虚报(无需按左键,被试按了左键:targetTask1=0 & respLeft=1)String block0Mubiao = jsonObject.getString("block0Mubiao");//block0的目标值String blockNum = jsonObject.getString("blockNum");//block编号  0-7  一共八个String itemTask1 = jsonObject.getString("itemTask1");//刺激的位置String level = jsonObject.getString("level");//当前block的难度等级:也即n-back任务的n值String respLeft = jsonObject.getString("respLeft");//被试的作答,是否按左键(即修改后的“位置”按钮,原来的“A”按钮):1,有按左键;0,没有按左键String targetTask1 = jsonObject.getString("targetTask1");//刺激是否是需要用户按键的目标刺激:0,不是;1,是String timer = jsonObject.getString("timer");//反应时String trainNum = jsonObject.getString("trainNum");//训练次数编号 1-160  最高160  有多少数就循环多少次String trialNum = jsonObject.getString("trialNum");//每个block内的trial编号 0-19  最高19   20个就清零NBlackJsonVO nBlackJsonVO = new NBlackJsonVO();nBlackJsonVO.setBlockNum(blockNum);nBlackJsonVO.setTimer(timer);nBlackJsonVO.setBlock0Mubiao(block0Mubiao);nBlackJsonVO.setItemTask1(itemTask1);nBlackJsonVO.setLevel(level);nBlackJsonVO.setTargetTask1(targetTask1);nBlackJsonVO.setTrainNum(trainNum);nBlackJsonVO.setTrialNum(trialNum);nBlackJsonVO.setRespLeft(respLeft);nBlackJsonVO.setSDTTask1(SDTTask1);nBlackJsonVOS.add(nBlackJsonVO);// 打印或处理这些字段的数据//每20个 建立一个list 然后向 nbackListHashMap加一个valueif ((i + 1) % 20 == 0) {//每20个清空nbackListHashMap.put(Integer.parseInt(blockNum), nBlackJsonVOS);nBlackJsonVOS = new ArrayList<>();}}//循环遍历我的mapint totalAccuracyOfVisualNumber = 0;ArrayList<Integer> totalReactionTimeList = new ArrayList<>();// 用于全部Block记录每轮的反应时间for (Map.Entry<Integer, List<NBlackJsonVO>> entry : nbackListHashMap.entrySet()) {// 创建一个数组来存储每轮的反应时间ArrayList<Integer> reactionTimeList = new ArrayList<>();// 用于记录每轮的反应时间int omissionErrorNumber = 0;//漏报次数  为2的int incorrectClassificationsNumber = 0; //错误次数 为4的int accuracyNnmber = 0;//其他Integer visualTestCategory = 1;//视觉分类任务Integer blockNum = null;Integer difficultyLevel = null;List<NBlackJsonVO> nabckList = entry.getValue();for (NBlackJsonVO nBlackJsonVO : nabckList) {String timer = nBlackJsonVO.getTimer();// 获取当前轮的 blockNumblockNum = Integer.parseInt(nBlackJsonVO.getBlockNum());// 获取难度等级difficultyLevel = Integer.parseInt(nBlackJsonVO.getLevel());// 将反应时间转换为 BigDecimalif (timer != null && !timer.isEmpty()) {// 将字符串转换为 BigDecimalBigDecimal currentReactionTime = new BigDecimal(timer);// 将当前轮的反应时间添加到总时间中reactionTimeList.add(currentReactionTime.intValue());//这个人所有back的用时数据totalReactionTimeList.add(currentReactionTime.intValue());}int sdtTask1 = Integer.parseInt(nBlackJsonVO.getSDTTask1());switch (sdtTask1) {case 2: // 漏报次数为2的情况omissionErrorNumber++;break;case 4: // 错误次数为4的情况incorrectClassificationsNumber++;break;default: // 其他情况accuracyNnmber++;//每个Nback正确数totalAccuracyOfVisualNumber++;//总正确数break;}}
// 计算平均反应时间// 计算平均反应时间double averageReactionTime = reactionTimeList.stream().mapToDouble(Integer::doubleValue).average().orElse(0.0);double averageReactionTimeOfCorrectVisualAnswers = totalReactionTimeList.stream().mapToDouble(Integer::doubleValue).average().orElse(0.0);
// 将平均时间四舍五入到整数int roundedAverageTime = (int) Math.round(averageReactionTime);int totalaverageReactionTimeOfCorrectVisualAnswers = (int) Math.round(averageReactionTimeOfCorrectVisualAnswers);BigDecimal accuracyRate = new BigDecimal(accuracyNnmber).divide(new BigDecimal(20), 2, RoundingMode.HALF_UP);BlockExcelVO blockExcelVO = new BlockExcelVO();blockExcelVO.setBlock(blockNum);blockExcelVO.setAccuracyRate(accuracyRate);blockExcelVO.setIncorrectClassificationsNumber(incorrectClassificationsNumber);blockExcelVO.setOmissionErrorNumber(omissionErrorNumber);blockExcelVO.setDifficultyLevel(difficultyLevel);blockExcelVO.setReactionTime(roundedAverageTime);blockExcelVO.setVisualTestCategory(1);//类别都是1//利用反射填充属性this.fillFieldsForNBack(e, blockExcelVO);e.setCompletionTime(g.getTotalTime());e.setAverageReactionTimeOfCorrectVisualAnswers(totalaverageReactionTimeOfCorrectVisualAnswers);//算出总正确率BigDecimal totalAccuracyOfVisualRate = new BigDecimal(totalAccuracyOfVisualNumber).divide(new BigDecimal(160), 2, RoundingMode.HALF_UP);e.setTotalAccuracyOfVisualRate(totalAccuracyOfVisualRate);System.out.println(e);}return e;}).collect(Collectors.toList());//查询情绪调节任务List<GaugeTestEntity> gaugesEmotionaTestlList = gaugeTestService.list(new QueryWrapper<GaugeTestEntity>().lambda().eq(GaugeTestEntity::getBatchId, gaugeRecord.getBatchId()).eq(GaugeTestEntity::getTestType, 1703));List<EmotionalRegulationExcel> emotionalRegulationExcelList = gaugesEmotionaTestlList.stream().map(g -> {TesterEntity tester = testerService.selectByIdNo(g.getUserId());EmotionalRegulationExcel e = new EmotionalRegulationExcel();e.setUserId(g.getUserId());e.setUserName(g.getUserName());e.setTestTime(g.getTestTime());e.setGender(CommonUtil.getGender(g.getUserId())==1?"男":"女");e.setBirthday(CommonUtil.getBirthday(g.getUserId()));e.setCompletionTime(g.getTotalTime());
//            e.setNaturalEmotionalResponseScore();//自然情绪得分
//            e.setEmotionalRegulationAbilityScore();//情绪调节能力得分
//			e.setBirthdayText(e.getBirthday()==null?"":e.getBirthday().format(DateTimeFormatter.ofPattern("yyyyMMdd")));if (tester != null) {}JSONArray jsonArrayQing = JSON.parseArray(g.getUserAnswer());ArrayList<Integer> aversiveNums = new ArrayList<>();ArrayList<Integer> neutralNums = new ArrayList<>();for (int i = 0; i < jsonArrayQing.size(); i++) {JSONObject jsonObject = jsonArrayQing.getJSONObject(i);Integer blockNum = jsonObject.getInteger("blockNum");//block编号Integer feel = jsonObject.getInteger("feel");//感受评分String lookType = jsonObject.getString("lookType");//look or lessString picType = jsonObject.getString("picType");//A or NString picName = jsonObject.getString("picName");//图片名称String showTime = jsonObject.getString("showTime");//显示时间String timer = jsonObject.getString("timer");//用时Integer trialNum = jsonObject.getInteger("trialNum");//block编号// 打印或处理这些字段的数据EmotionalExcelVO emotionalExcelVO = new EmotionalExcelVO();emotionalExcelVO.setBlock(blockNum);emotionalExcelVO.setEmotionalAssessmentScore(feel);emotionalExcelVO.setPictureValenceAndSerialNumber(picName);emotionalExcelVO.setEmotionalRegulationStrategy(picType.equals("look") ? 1 : 2);emotionalExcelVO.setTrial(trialNum);//自然情绪反应得分 计算【20张厌恶图片观察得分的平均值】-【20张中性图片观察得分的平均值】,得分范围0-100if (picType.equals("Aversive")){aversiveNums.add(feel);}else {neutralNums.add(feel);}//情绪调节能力得分  计算【20张厌恶图片观察得分的平均值】-【35张厌恶图片改变得分的平均值】this.fillFieldsForQing(e, emotionalExcelVO);}//自然情绪反应得分List<Integer> aversiveNum_0_20 = aversiveNums.subList(0, 20);List<Integer> neutralNum_0_20 = neutralNums.subList(0, 20);List<Integer> aversiveNum_0_35 = aversiveNums.subList(0, 35);// 计算平均反应时间double averageAversiveNum_0_20 = aversiveNum_0_20.stream().mapToDouble(Integer::doubleValue).average().orElse(0.0);double averageNeutralNum_0_20 = neutralNum_0_20.stream().mapToDouble(Integer::doubleValue).average().orElse(0.0);double averageAversiveNum_0_35 = aversiveNum_0_35.stream().mapToDouble(Integer::doubleValue).average().orElse(0.0);BigDecimal subtract0 = new BigDecimal(averageAversiveNum_0_20).subtract(new BigDecimal(averageNeutralNum_0_20));BigDecimal subtract1 = new BigDecimal(averageAversiveNum_0_20).subtract(new BigDecimal(averageAversiveNum_0_35));
//				e.setNaturalEmotionalResponseScore(subtract0);  这俩先不导出,因为规则有问题
//				e.setEmotionalRegulationAbilityScore(subtract1);return e;}).collect(Collectors.toList());// 设置响应类型为Excel文件response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("UTF-8");
// 设置Excel文件名response.setHeader("Content-disposition", "attachment;filename=" + "SYNL" + ".xlsx");try {if (!CollectionUtils.isEmpty(excels)) {// 创建ExcelWriter并指定输出流为response.getOutputStream()ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).excelType(ExcelTypeEnum.XLSX).build();// 写入三个sheet的数据WriteSheet writeSheet = EasyExcel.writerSheet(0, "适应能力").head(GaugeTestExcel.class).build();excelWriter.write(excels, writeSheet);WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "工作记忆任务").head(NBackTestExcel.class).build();excelWriter.write(nbackExcels, writeSheet1);WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "情绪调节任务").head(EmotionalRegulationExcel.class).build();excelWriter.write(emotionalRegulationExcelList, writeSheet2);excelWriter.finish();}} catch (Exception e) {e.printStackTrace();} finally {try {response.getOutputStream().flush();response.getOutputStream().close();} catch (IOException e) {e.printStackTrace();}}}

三个list本质上并没有关联,可以分开处理,利用三个线程正好,等待处理完成,把list收集起来

,改良后

   /*** 导出excel*/@GetMapping("/export/excel")@ApiOperationSupport(order = 11)@ApiOperation(value = "导出excel", notes = "传入gaugeRecord")public void exportExcel(GaugeRecordEntity gaugeRecord, HttpServletResponse response) throws IOException {GaugeTestEntity testCondition = new GaugeTestEntity();testCondition.setBatchId(gaugeRecord.getBatchId());
//		testCondition.setSiteCode(gaugeRecord.getSiteCode());// 查询所有人的基本信息List<TesterEntity> allTesters = testerService.list();
// 将所有人的信息转换为 id 和 entity 的 HashMapMap<String, TesterEntity> testerMap = allTesters.stream().collect(Collectors.toMap(TesterEntity::getIdNo, Function.identity()));List<GaugeTestExcel> excels = null;List<NBackTestExcel> nbackExcels= null;List<EmotionalRegulationExcel> emotionalRegulationExcelList = null;AtomicReference<List<GaugeTestExcel>> excelsRef = new AtomicReference<>(excels);AtomicReference<List<NBackTestExcel>> excelsRef02 = new AtomicReference<>(nbackExcels);AtomicReference<List<EmotionalRegulationExcel>> excelsRef03 = new AtomicReference<>(emotionalRegulationExcelList);// 使用线程池并行处理不同的数据导出任务//输出线程号加上时间System.out.println("当前线程"+Thread.currentThread().getId() + " " + LocalDateTime.now());ExecutorService executorService = Executors.newFixedThreadPool(3);CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> {List<GaugeTestEntity> gauges = gaugeTestService.selectEffectiveGauge(testCondition);List<GaugeTestExcel>   excelsAsync = gauges.stream().map(g -> {TesterEntity tester = testerMap.get(g.getUserId());GaugeTestExcel e = new GaugeTestExcel();e.setUserId(g.getUserId());e.setUserName(g.getUserName());e.setTestTime(g.getTestTime());e.setGender(CommonUtil.getGender(g.getUserId()) == 1 ? "男" : "女");e.setBirthday(CommonUtil.getBirthday(g.getUserId()));
//			e.setBirthdayText(e.getBirthday()==null?"":e.getBirthday().format(DateTimeFormatter.ofPattern("yyyyMMdd")));if (tester != null) {e.setEducationText(DictBizCache.getValue(DictBizEnum.EDUCATION, tester.getEducation()));e.setEducationYears(tester.getEducationYears());e.setIsOnlychildText(DictBizCache.getValue(DictBizEnum.ONLY_CHILD, tester.getIsOnlychild()));if (!DictBizCache.getValue(DictBizEnum.ONLY_CHILD, tester.getIsOnlychild()).equals("独生子女")) {e.setChildrenQty(tester.getChildrenQty());e.setChildrenRanking(tester.getChildrenRanking());}e.setSubjectiveSes(tester.getSubjectiveSes());e.setFamilyMonthlyEarningText(DictBizCache.getValue(DictBizEnum.FAMILY_MONTHLY_EARNING, tester.getFamilyMonthlyEarning()));e.setEducationMotherText(DictBizCache.getValue(DictBizEnum.PARENT_EDUCATION, tester.getEducationMother()));e.setEducationFantherText(DictBizCache.getValue(DictBizEnum.PARENT_EDUCATION, tester.getEducationFanther()));}JSONObject statistical = JSON.parseObject(g.getStatistical());e.setTaiyin(statistical.get("太阴人格") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("太阴人格").toString()));e.setYanjinxing(statistical.get("严谨性人格") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("严谨性人格").toString()));e.setShenjingzhi(statistical.get("神经质人格") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("神经质人格").toString()));e.setRengetezhi(statistical.get("人格特质") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("人格特质").toString()));e.setTezhijiaolv(statistical.get("特质焦虑") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("特质焦虑").toString()));e.setShenghuomanyidu(statistical.get("生活满意度") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("生活满意度").toString()));e.setShengmingyiyigan(statistical.get("生命意义感") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("生命意义感").toString()));e.setZizun(statistical.get("自尊") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("自尊").toString()));e.setZhuguanxingfugan(statistical.get("主观幸福感") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("主观幸福感").toString()));e.setYalizhijue(statistical.get("压力知觉") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("压力知觉").toString()));e.setYiyu(statistical.get("抑郁") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("抑郁").toString()));e.setXinlijiankang(statistical.get("心理健康") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("心理健康").toString()));e.setJijiyingdui(statistical.get("积极应对") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("积极应对").toString()));e.setXiaojiyingdui(statistical.get("消极应对") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("消极应对").toString()));e.setQingxutiaojie(statistical.get("情绪调节") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("情绪调节").toString()));e.setXinlitanxing(statistical.get("心理弹性") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("心理弹性").toString()));e.setZiwoxiaonenggan(statistical.get("自我效能感") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("自我效能感").toString()));e.setYaliyingdui(statistical.get("压力应对") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("压力应对").toString()));e.setRenjiqinggan(statistical.get("人际情感") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("人际情感").toString()));e.setRenjichongtu(statistical.get("人际冲突") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("人际冲突").toString()));e.setQinshehui(statistical.get("亲社会倾向") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("亲社会倾向").toString()));e.setGongji(statistical.get("攻击") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("攻击").toString()));e.setRenjiguanxi(statistical.get("人际关系") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("人际关系").toString()));e.setShiyingnengli(statistical.get("适应能力") == null ? BigDecimal.ZERO : new BigDecimal(statistical.get("适应能力").toString()));JSONObject answer = JSON.parseObject(g.getUserAnswer());e.setQ1((String) answer.get("Q1"));e.setQ2((String) answer.get("Q2"));e.setQ3((String) answer.get("Q3"));e.setQ4((String) answer.get("Q4"));e.setQ5((String) answer.get("Q5"));e.setQ6((String) answer.get("Q6"));e.setQ7((String) answer.get("Q7"));e.setQ8((String) answer.get("Q8"));e.setQ9((String) answer.get("Q9"));e.setQ10((String) answer.get("Q10"));e.setQ11((String) answer.get("Q11"));e.setQ12((String) answer.get("Q12"));e.setQ13((String) answer.get("Q13"));e.setQ14((String) answer.get("Q14"));e.setQ15((String) answer.get("Q15"));e.setQ16((String) answer.get("Q16"));e.setQ17((String) answer.get("Q17"));e.setQ18((String) answer.get("Q18"));e.setQ19((String) answer.get("Q19"));e.setQ20((String) answer.get("Q20"));e.setQ21((String) answer.get("Q21"));e.setQ22((String) answer.get("Q22"));e.setQ23((String) answer.get("Q23"));e.setQ24((String) answer.get("Q24"));e.setQ25((String) answer.get("Q25"));e.setQ26((String) answer.get("Q26"));e.setQ27((String) answer.get("Q27"));e.setQ28((String) answer.get("Q28"));e.setQ29((String) answer.get("Q29"));e.setQ30((String) answer.get("Q30"));e.setQ31((String) answer.get("Q31"));e.setQ32((String) answer.get("Q32"));e.setQ33((String) answer.get("Q33"));e.setQ34((String) answer.get("Q34"));e.setQ35((String) answer.get("Q35"));e.setQ36((String) answer.get("Q36"));e.setQ37((String) answer.get("Q37"));e.setQ38((String) answer.get("Q38"));e.setQ39((String) answer.get("Q39"));e.setQ40((String) answer.get("Q40"));e.setQ41((String) answer.get("Q41"));e.setQ42((String) answer.get("Q42"));e.setQ43((String) answer.get("Q43"));e.setQ44((String) answer.get("Q44"));e.setQ45((String) answer.get("Q45"));e.setQ46((String) answer.get("Q46"));e.setQ47((String) answer.get("Q47"));e.setQ48((String) answer.get("Q48"));e.setQ49((String) answer.get("Q49"));e.setQ50((String) answer.get("Q50"));e.setQ51((String) answer.get("Q51"));e.setQ52((String) answer.get("Q52"));e.setQ53((String) answer.get("Q53"));e.setQ54((String) answer.get("Q54"));e.setQ55((String) answer.get("Q55"));e.setQ56((String) answer.get("Q56"));e.setQ57((String) answer.get("Q57"));e.setQ58((String) answer.get("Q58"));e.setQ59((String) answer.get("Q59"));return e;}).collect(Collectors.toList());excelsRef.set(excelsAsync);
//输出线程号加上时间System.out.println("当前线程"+Thread.currentThread().getId() + " " + LocalDateTime.now());}, executorService);//查询工作记忆任务CompletableFuture<Void> task2 = CompletableFuture.runAsync(() -> {List<GaugeTestEntity> gaugesGong = gaugeTestService.list(new QueryWrapper<GaugeTestEntity>().lambda().eq(GaugeTestEntity::getBatchId, gaugeRecord.getBatchId()).eq(GaugeTestEntity::getTestType, 1707));List<NBackTestExcel> nbackExcelsAsync = gaugesGong.stream().map(g -> {TesterEntity tester = testerService.selectByIdNo(g.getUserId());NBackTestExcel e = new NBackTestExcel();e.setUserId(g.getUserId());e.setUserName(g.getUserName());e.setTestTime(g.getTestTime());e.setGender(CommonUtil.getGender(g.getUserId()) == 1 ? "男" : "女");e.setBirthday(CommonUtil.getBirthday(g.getUserId()));
//			e.setBirthdayText(e.getBirthday()==null?"":e.getBirthday().format(DateTimeFormatter.ofPattern("yyyyMMdd")));if (tester != null) {}//构建hashMap来存各个block的对象HashMap<Integer, List<NBlackJsonVO>> nbackListHashMap = new HashMap<>();ArrayList<NBlackJsonVO> nBlackJsonVOS = new ArrayList<>();//JSONArray jsonArrayNBack = JSON.parseArray(g.getUserAnswer());//一共160个for (int i = 0; i < jsonArrayNBack.size(); i++) {JSONObject jsonObject = jsonArrayNBack.getJSONObject(i);String SDTTask1 = jsonObject.getString("SDTTask1");//任务一的信号检测论指标:1击中(应该按左键,被试按了左键: targetTask1=1 & respLeft=1),2漏报(应该按左键,被试没按左键:targetTask1=1 & respLeft = 0),3正确拒斥(无需按左键,被试没按左键:targetTask1=0 & respLeft =0),4虚报(无需按左键,被试按了左键:targetTask1=0 & respLeft=1)String block0Mubiao = jsonObject.getString("block0Mubiao");//block0的目标值String blockNum = jsonObject.getString("blockNum");//block编号  0-7  一共八个String itemTask1 = jsonObject.getString("itemTask1");//刺激的位置String level = jsonObject.getString("level");//当前block的难度等级:也即n-back任务的n值String respLeft = jsonObject.getString("respLeft");//被试的作答,是否按左键(即修改后的“位置”按钮,原来的“A”按钮):1,有按左键;0,没有按左键String targetTask1 = jsonObject.getString("targetTask1");//刺激是否是需要用户按键的目标刺激:0,不是;1,是String timer = jsonObject.getString("timer");//反应时String trainNum = jsonObject.getString("trainNum");//训练次数编号 1-160  最高160  有多少数就循环多少次String trialNum = jsonObject.getString("trialNum");//每个block内的trial编号 0-19  最高19   20个就清零NBlackJsonVO nBlackJsonVO = new NBlackJsonVO();nBlackJsonVO.setBlockNum(blockNum);nBlackJsonVO.setTimer(timer);nBlackJsonVO.setBlock0Mubiao(block0Mubiao);nBlackJsonVO.setItemTask1(itemTask1);nBlackJsonVO.setLevel(level);nBlackJsonVO.setTargetTask1(targetTask1);nBlackJsonVO.setTrainNum(trainNum);nBlackJsonVO.setTrialNum(trialNum);nBlackJsonVO.setRespLeft(respLeft);nBlackJsonVO.setSDTTask1(SDTTask1);nBlackJsonVOS.add(nBlackJsonVO);// 打印或处理这些字段的数据//每20个 建立一个list 然后向 nbackListHashMap加一个valueif ((i + 1) % 20 == 0) {//每20个清空nbackListHashMap.put(Integer.parseInt(blockNum), nBlackJsonVOS);nBlackJsonVOS = new ArrayList<>();}}//循环遍历我的mapint totalAccuracyOfVisualNumber = 0;ArrayList<Integer> totalReactionTimeList = new ArrayList<>();// 用于全部Block记录每轮的反应时间for (Map.Entry<Integer, List<NBlackJsonVO>> entry : nbackListHashMap.entrySet()) {// 创建一个数组来存储每轮的反应时间ArrayList<Integer> reactionTimeList = new ArrayList<>();// 用于记录每轮的反应时间int omissionErrorNumber = 0;//漏报次数  为2的int incorrectClassificationsNumber = 0; //错误次数 为4的int accuracyNnmber = 0;//其他Integer visualTestCategory = 1;//视觉分类任务Integer blockNum = null;Integer difficultyLevel = null;List<NBlackJsonVO> nabckList = entry.getValue();for (NBlackJsonVO nBlackJsonVO : nabckList) {String timer = nBlackJsonVO.getTimer();// 获取当前轮的 blockNumblockNum = Integer.parseInt(nBlackJsonVO.getBlockNum());// 获取难度等级difficultyLevel = Integer.parseInt(nBlackJsonVO.getLevel());// 将反应时间转换为 BigDecimalif (timer != null && !timer.isEmpty()) {// 将字符串转换为 BigDecimalBigDecimal currentReactionTime = new BigDecimal(timer);// 将当前轮的反应时间添加到总时间中reactionTimeList.add(currentReactionTime.intValue());//这个人所有back的用时数据totalReactionTimeList.add(currentReactionTime.intValue());}int sdtTask1 = Integer.parseInt(nBlackJsonVO.getSDTTask1());switch (sdtTask1) {case 2: // 漏报次数为2的情况omissionErrorNumber++;break;case 4: // 错误次数为4的情况incorrectClassificationsNumber++;break;default: // 其他情况accuracyNnmber++;//每个Nback正确数totalAccuracyOfVisualNumber++;//总正确数break;}}
// 计算平均反应时间// 计算平均反应时间double averageReactionTime = reactionTimeList.stream().mapToDouble(Integer::doubleValue).average().orElse(0.0);double averageReactionTimeOfCorrectVisualAnswers = totalReactionTimeList.stream().mapToDouble(Integer::doubleValue).average().orElse(0.0);
// 将平均时间四舍五入到整数int roundedAverageTime = (int) Math.round(averageReactionTime);int totalaverageReactionTimeOfCorrectVisualAnswers = (int) Math.round(averageReactionTimeOfCorrectVisualAnswers);BigDecimal accuracyRate = new BigDecimal(accuracyNnmber).divide(new BigDecimal(20), 2, RoundingMode.HALF_UP);BlockExcelVO blockExcelVO = new BlockExcelVO();blockExcelVO.setBlock(blockNum);blockExcelVO.setAccuracyRate(accuracyRate);blockExcelVO.setIncorrectClassificationsNumber(incorrectClassificationsNumber);blockExcelVO.setOmissionErrorNumber(omissionErrorNumber);blockExcelVO.setDifficultyLevel(difficultyLevel);blockExcelVO.setReactionTime(roundedAverageTime);blockExcelVO.setVisualTestCategory(1);//类别都是1//利用反射填充属性this.fillFieldsForNBack(e, blockExcelVO);e.setCompletionTime(g.getTotalTime());e.setAverageReactionTimeOfCorrectVisualAnswers(totalaverageReactionTimeOfCorrectVisualAnswers);//算出总正确率BigDecimal totalAccuracyOfVisualRate = new BigDecimal(totalAccuracyOfVisualNumber).divide(new BigDecimal(160), 2, RoundingMode.HALF_UP);e.setTotalAccuracyOfVisualRate(totalAccuracyOfVisualRate);System.out.println(e);}return e;}).collect(Collectors.toList());excelsRef02.set(nbackExcelsAsync);
//输出线程号加上时间System.out.println("当前线程"+Thread.currentThread().getId() + " " + LocalDateTime.now());}, executorService);CompletableFuture<Void> task3 = CompletableFuture.runAsync(() -> {//查询情绪调节任务List<GaugeTestEntity> gaugesEmotionaTestlList = gaugeTestService.list(new QueryWrapper<GaugeTestEntity>().lambda().eq(GaugeTestEntity::getBatchId, gaugeRecord.getBatchId()).eq(GaugeTestEntity::getTestType, 1703));List<EmotionalRegulationExcel>    emotionalRegulationExcelListAsync = gaugesEmotionaTestlList.stream().map(g -> {TesterEntity tester = testerService.selectByIdNo(g.getUserId());EmotionalRegulationExcel e = new EmotionalRegulationExcel();e.setUserId(g.getUserId());e.setUserName(g.getUserName());e.setTestTime(g.getTestTime());e.setGender(CommonUtil.getGender(g.getUserId()) == 1 ? "男" : "女");e.setBirthday(CommonUtil.getBirthday(g.getUserId()));e.setCompletionTime(g.getTotalTime());
//            e.setNaturalEmotionalResponseScore();//自然情绪得分
//            e.setEmotionalRegulationAbilityScore();//情绪调节能力得分
//			e.setBirthdayText(e.getBirthday()==null?"":e.getBirthday().format(DateTimeFormatter.ofPattern("yyyyMMdd")));if (tester != null) {}JSONArray jsonArrayQing = JSON.parseArray(g.getUserAnswer());ArrayList<Integer> aversiveNums = new ArrayList<>();ArrayList<Integer> neutralNums = new ArrayList<>();for (int i = 0; i < jsonArrayQing.size(); i++) {JSONObject jsonObject = jsonArrayQing.getJSONObject(i);Integer blockNum = jsonObject.getInteger("blockNum");//block编号Integer feel = jsonObject.getInteger("feel");//感受评分String lookType = jsonObject.getString("lookType");//look or lessString picType = jsonObject.getString("picType");//A or NString picName = jsonObject.getString("picName");//图片名称String showTime = jsonObject.getString("showTime");//显示时间String timer = jsonObject.getString("timer");//用时Integer trialNum = jsonObject.getInteger("trialNum");//block编号// 打印或处理这些字段的数据EmotionalExcelVO emotionalExcelVO = new EmotionalExcelVO();emotionalExcelVO.setBlock(blockNum);emotionalExcelVO.setEmotionalAssessmentScore(feel);emotionalExcelVO.setPictureValenceAndSerialNumber(picName);emotionalExcelVO.setEmotionalRegulationStrategy(picType.equals("look") ? 1 : 2);emotionalExcelVO.setTrial(trialNum);//自然情绪反应得分 计算【20张厌恶图片观察得分的平均值】-【20张中性图片观察得分的平均值】,得分范围0-100if (picType.equals("Aversive")) {aversiveNums.add(feel);} else {neutralNums.add(feel);}//情绪调节能力得分  计算【20张厌恶图片观察得分的平均值】-【35张厌恶图片改变得分的平均值】this.fillFieldsForQing(e, emotionalExcelVO);}//自然情绪反应得分List<Integer> aversiveNum_0_20 = aversiveNums.subList(0, 20);List<Integer> neutralNum_0_20 = neutralNums.subList(0, 20);List<Integer> aversiveNum_0_35 = aversiveNums.subList(0, 35);// 计算平均反应时间double averageAversiveNum_0_20 = aversiveNum_0_20.stream().mapToDouble(Integer::doubleValue).average().orElse(0.0);double averageNeutralNum_0_20 = neutralNum_0_20.stream().mapToDouble(Integer::doubleValue).average().orElse(0.0);double averageAversiveNum_0_35 = aversiveNum_0_35.stream().mapToDouble(Integer::doubleValue).average().orElse(0.0);BigDecimal subtract0 = new BigDecimal(averageAversiveNum_0_20).subtract(new BigDecimal(averageNeutralNum_0_20));BigDecimal subtract1 = new BigDecimal(averageAversiveNum_0_20).subtract(new BigDecimal(averageAversiveNum_0_35));
//				e.setNaturalEmotionalResponseScore(subtract0);  这俩先不导出,因为规则有问题
//				e.setEmotionalRegulationAbilityScore(subtract1);return e;}).collect(Collectors.toList());
//输出线程号加上时间System.out.println(Thread.currentThread().getId() + " " + LocalDateTime.now());excelsRef03.set(emotionalRegulationExcelListAsync);}, executorService);// 等待所有任务完成CompletableFuture.allOf(task1, task2, task3).join();// 从AtomicReference获取最终的excels列表excels = excelsRef.get();nbackExcels = excelsRef02.get();emotionalRegulationExcelList = excelsRef03.get();// 设置响应类型为Excel文件response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("UTF-8");
// 设置Excel文件名response.setHeader("Content-disposition", "attachment;filename=" + "SYNL" + ".xlsx");try {if (!CollectionUtils.isEmpty(excels)) {// 创建ExcelWriter并指定输出流为response.getOutputStream()ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).excelType(ExcelTypeEnum.XLSX).build();// 写入三个sheet的数据WriteSheet writeSheet = EasyExcel.writerSheet(0, "适应能力").head(GaugeTestExcel.class).build();excelWriter.write(excels, writeSheet);WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "工作记忆任务").head(NBackTestExcel.class).build();excelWriter.write(nbackExcels, writeSheet1);WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "情绪调节任务").head(EmotionalRegulationExcel.class).build();excelWriter.write(emotionalRegulationExcelList, writeSheet2);excelWriter.finish();}} catch (Exception e) {e.printStackTrace();} finally {try {response.getOutputStream().flush();response.getOutputStream().close();} catch (IOException e) {e.printStackTrace();}}}

经过多线程优化,时间由原来的两分钟,缩减到三分

代码简化如下:

    /*** 导出excel*/@GetMapping("/export/excel")@ApiOperationSupport(order = 11)@ApiOperation(value = "导出excel", notes = "传入gaugeRecord")public void exportExcel(GaugeRecordEntity gaugeRecord, HttpServletResponse response) throws IOException {ExecutorService executorService = Executors.newFixedThreadPool(3);List<GaugeTestExcel> excels = null;List<NBackTestExcel> nbackExcels = null;List<EmotionalRegulationExcel> emotionalRegulationExcelList = null;try {GaugeTestEntity testCondition = new GaugeTestEntity();testCondition.setBatchId(gaugeRecord.getBatchId());
//		testCondition.setSiteCode(gaugeRecord.getSiteCode());// 查询所有人的基本信息List<TesterEntity> allTesters = testerService.list();
// 将所有人的信息转换为 id 和 entity 的 HashMapMap<String, TesterEntity> testerMap = allTesters.stream().collect(Collectors.toMap(TesterEntity::getIdNo, Function.identity()));AtomicReference<List<GaugeTestExcel>> excelsRef = new AtomicReference<>(excels);AtomicReference<List<NBackTestExcel>> excelsRef02 = new AtomicReference<>(nbackExcels);AtomicReference<List<EmotionalRegulationExcel>> excelsRef03 = new AtomicReference<>(emotionalRegulationExcelList);// 使用线程池并行处理不同的数据导出任务//输出线程号加上时间System.out.println("当前线程" + Thread.currentThread().getId() + " " + LocalDateTime.now());CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> {List<GaugeTestEntity> gauges = gaugeTestService.selectEffectiveGauge(testCondition);List<GaugeTestExcel> excelsAsync = gauges.stream().map(g -> {//中间代码省略return e;}).collect(Collectors.toList());excelsRef.set(excelsAsync);
//输出线程号加上时间System.out.println("当前线程" + Thread.currentThread().getId() + " " + LocalDateTime.now());}, executorService);//查询工作记忆任务CompletableFuture<Void> task2 = CompletableFuture.runAsync(() -> {List<GaugeTestEntity> gaugesGong = gaugeTestService.list(new QueryWrapper<GaugeTestEntity>().lambda().eq(GaugeTestEntity::getBatchId, gaugeRecord.getBatchId()).eq(GaugeTestEntity::getTestType, 1707));List<NBackTestExcel> nbackExcelsAsync = gaugesGong.stream().map(g -> {//中间代码省略return e;}).collect(Collectors.toList());excelsRef02.set(nbackExcelsAsync);
//输出线程号加上时间System.out.println("当前线程" + Thread.currentThread().getId() + " " + LocalDateTime.now());}, executorService);CompletableFuture<Void> task3 = CompletableFuture.runAsync(() -> {//查询情绪调节任务List<GaugeTestEntity> gaugesEmotionaTestlList = gaugeTestService.list(new QueryWrapper<GaugeTestEntity>().lambda().eq(GaugeTestEntity::getBatchId, gaugeRecord.getBatchId()).eq(GaugeTestEntity::getTestType, 1703));List<EmotionalRegulationExcel> emotionalRegulationExcelListAsync = gaugesEmotionaTestlList.stream().map(g -> {//中间代码省略return e;}).collect(Collectors.toList());
//输出线程号加上时间System.out.println(Thread.currentThread().getId() + " " + LocalDateTime.now());excelsRef03.set(emotionalRegulationExcelListAsync);}, executorService);// 等待所有任务完成CompletableFuture.allOf(task1, task2, task3).join();// 从AtomicReference获取最终的excels列表excels = excelsRef.get();nbackExcels = excelsRef02.get();emotionalRegulationExcelList = excelsRef03.get();} catch (Exception e) {e.printStackTrace();} finally {// 销毁线程池executorService.shutdownNow();}// 设置响应类型为Excel文件response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("UTF-8");
// 设置Excel文件名response.setHeader("Content-disposition", "attachment;filename=" + "SYNL" + ".xlsx");try {if (!CollectionUtils.isEmpty(excels)) {// 创建ExcelWriter并指定输出流为response.getOutputStream()ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).excelType(ExcelTypeEnum.XLSX).build();// 写入三个sheet的数据WriteSheet writeSheet = EasyExcel.writerSheet(0, "适应能力").head(GaugeTestExcel.class).build();excelWriter.write(excels, writeSheet);WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "工作记忆任务").head(NBackTestExcel.class).build();excelWriter.write(nbackExcels, writeSheet1);WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "情绪调节任务").head(EmotionalRegulationExcel.class).build();excelWriter.write(emotionalRegulationExcelList, writeSheet2);excelWriter.finish();}} catch (Exception e) {e.printStackTrace();} finally {try {response.getOutputStream().flush();response.getOutputStream().close();} catch (IOException e) {e.printStackTrace();}}}

其中很重要的问题,为什么要用AtomicReference

在代码示例中,Lambda表达式中尝试修改了外部变量excels,而excels是在外部声明的ArrayList,这会导致“Variable used in lambda expression should be final or effectively final”的编译错误。

为了解决这个问题,可以将excels声明为一个AtomicReference类型,这样就能在Lambda表达式中修改其引用指向的对象,而不改变它本身的引用。

通过将excels声明为AtomicReference类型,并使用AtomicReferenceset方法来修改引用指向的对象,可以在Lambda表达式中正确地更新excels列表,同时避免了编译错误。最后,您可以通过AtomicReferenceget方法获取最终的excels列表。

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

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

相关文章

Day57:WEB攻防-SSRF服务端请求Gopher伪协议无回显利用黑白盒挖掘业务功能点

目录 SSRF-原理&挖掘&利用&修复 SSRF无回显解决办法 SSRF漏洞挖掘 SSRF协议利用 http:// &#xff08;常用&#xff09; file:/// &#xff08;常用&#xff09; dict:// &#xff08;常用&#xff09; sftp:// ldap:// tftp:// gopher:// &#xff08;…

群晖NAS使用Docker部署大语言模型Llama 2结合内网穿透实现公网访问本地GPT聊天服务

文章目录 1. 拉取相关的Docker镜像2. 运行Ollama 镜像3. 运行Chatbot Ollama镜像4. 本地访问5. 群晖安装Cpolar6. 配置公网地址7. 公网访问8. 固定公网地址 随着ChatGPT 和open Sora 的热度剧增,大语言模型时代,开启了AI新篇章,大语言模型的应用非常广泛&#xff0c;包括聊天机…

Nginx漏洞之未授权访问和源码泄漏漏洞处理

一、漏洞描述 某次安全扫描&#xff0c;发现某平台存在资源&#xff1a;未授权访问和源码泄漏&#xff1b;攻击者可能获取到网站的配置文件、敏感数据存储位置和访问凭证等信息。这意味着攻击者可以获得对网站的完全或部分控制权&#xff0c;进而进行恶意篡改、删除或添加恶意…

6.8物联网RK3399项目开发实录-驱动开发之RTC实时时钟的使用(wulianjishu666)

90款行业常用传感器单片机程序及资料【stm32,stc89c52,arduino适用】 链接&#xff1a;https://pan.baidu.com/s/1M3u8lcznKuXfN8NRoLYtTA?pwdc53f RTC 使用 简介 AIO-3399J 开发板上有 一个集成于 RK808 上的RTC(Real Time Clock)&#xff0c;主要功能有时钟&#xff0c…

Matlab安装完成后打开后闪退

官方解决办法&#xff0c;英文看着费劲 其中Problem #2和Problem #4大概率能解决问题我是使用Problem #4解决的&#xff0c;引发原因是Problem #3加密软件导致&#xff0c;只能先命令行再desktop才能打开软件 知乎绵绵给出的方法&#xff0c;和官方解决相同但是中文

【PowerDesigner】PGSQL反向工程过程已中断

问题 反向工程过程已中断,原因是某些字符无法通过ANSI–&#xff1e;UTF-16转换进行映射。pg导入sql时报错&#xff0c;一查询是power designer 反向工程过程已中断&#xff0c;某些字符无法通过ANSI–>UTF-16转换进行映射&#xff08;会导致数据丢失&#xff09; 处理 注…

代码随想录第28天| 131.分割回文串 93.复原IP地址 78.子集

131.分割回文串 131. 分割回文串 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 带你学透回溯算法-分割回文串&#xff08;对应力扣题目&#xff1a;131.分割回文串&#xff09;| 回溯法精讲&#xff01;_哔哩哔哩_bilibili 给你一个字符串 s&…

armbian等linux系统修改fstab实现开机自动挂载磁盘(详解)

当 Linux 操作系统启动时&#xff0c;它会尝试挂载您的硬盘和其他存储设备上的分区。为了实现这一目标&#xff0c;系统使用 /etc/fstab 文件来确定应该如何挂载文件系统。/etc/fstab 文件是一个文本文件&#xff0c;包含了在系统引导期间将要挂载的所有文件系统的定义。它通过…

关于投标的细节

第一点&#xff1a; 进来的时候记住到达时间&#xff0c;这个时间只能是个参考。签到表时间填写要符合逻辑性&#xff0c;就是来的比你早的到达时间一定比你的晚&#xff0c;来的比你晚的到达时间一定比你迟。优先考虑的是先后而不是真实到达时间。除非你是第一个填写的 第二点…

如何创建自己的 Spring Boot Starter 并为其编写单元测试

当我们想要封装一些自定义功能给别人使用的时候&#xff0c;创建Spring Boot Starter的形式是最好的实现方式。如果您还不会构建自己的Spring Boot Starter的话&#xff0c;本文将带你一起创建一个自己的Spring Boot Starter。 快速入门 创建一个新的 Maven 项目。第三方封装的…

连接Redis不支持集群错误,ERR This instance has cluster support disabled,解决方案

1. 问题背景 调整redis的配置后&#xff0c;启动程序时&#xff0c; 会报如下错误&#xff1a; [redis://172.16.0.8xxx]: ERR This instance has cluster support disabledSuppressed: io.lettuce.core.RedisCommandExecutionException: ERR This instance has cluster supp…

TypeScript-数组、函数类型

1.数组类型 1.1类型 方括号 let arry:number[][5,2,0,1,3,1,4] 1.2 数组泛型 let arry2:Array<number>[5,2,0,1,3,1,4] 1.3接口类型 interface makeArryRule{[index:number]:number }let arry3:makeArryRule[5,2,0,1,3,1,4] 1.4伪数组 说明&#xff1a; argument…

MyBatis数据库逆向生成工具

使用Mybatis数据库逆向生成工具 1.在pom中引入通用mapper工具 <!-- 通用mapper逆向工具 --><dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId><version>1.2.4</version></d…

苹果安卓双端短视频直播系统源码,带后台-支持二开和采集

搭建教程 1.PHP5.6-7.2 mysql 5.6 redis5.0 nginx1.15 2.宝塔就完全满足了 我刚开了台服务器&#xff0c;建议用阿里云的 我这个是腾讯云 先让服务器 自己装着 时间比较长 3.搭建前需要准备的东西 腾讯云直播、七牛存储、百度语音、腾讯地图等好多东西 七牛存储…

面试算法4/400-乘积小于 K 的子数组

题目 给定一个正整数数组 nums和整数 k &#xff0c;请找出该数组内乘积小于 k 的连续的子数组的个数。 示例 1: 输入: nums [10,5,2,6], k 100 输出: 8 解释: 8 个乘积小于 100 的子数组分别为: [10], [5], [2], [6], [10,5], [5,2], [2,6], [5,2,6]。 需要注意的是 [10,…

Micron FY24 Q2业绩强劲,凭内存实现翻盘

根据TechInsights数据显示&#xff0c;美光科技24财年第二季度业绩强劲&#xff0c;公司通过技术创新和产能优化&#xff0c;成功抓住了AI服务器和其他高性能应用带来的市场需求增长机遇。尽管短期内面临供应紧张的问题&#xff0c;但美光通过加大研发投入和产能转换力度&#…

蓝桥杯算法基础(30):尺取法的应用(hiho字符串),next数组应用(前缀周期性),后缀数组的应用

尺取法应用题hiho字符串 如果一个字符串恰好包含2个h,1个‘1’和1个‘0’&#xff0c;我们就称这个字符串是hiho字符串 例如"oihateher"、“hugeinputhugeoutput”都是hiho字符串 现在给定一个只包含小写字母的字符串S&#xff0c;小H想知道S的所有子串中&#xff0c…

Leetcode 322. 零钱兑换

心路历程&#xff1a; 这道题和上一道完全平方数的和基本上一摸一样&#xff0c;甚至比上一道题还简单&#xff0c;基于dp的建模&#xff1a; 状态&#xff1a;当前的目标总金额 动作&#xff1a;选哪一个硬币 返回值&#xff1a;凑成该目标总金额的最少硬币个数 这道题如果硬…

2024.4.2

模拟面试&#xff1a; 一、GPIO是什么&#xff1f; 答&#xff1a;通用输入输出接口&#xff0c;可以作为单片机和外部设备连接的桥梁。 二、VCC是什么? VCC通常是多少V? 答&#xff1a;电源&#xff0c;通常是3.3V和5V。 三、FreeRTOS任务有几种状态&#xff0c;分别是…

MATLAB科研绘图与学术图表绘制从入门到精通

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…