遇到了业务上处理很慢的情况,都可以用多线程解决,这是原先未优化的代码
/*** 导出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
类型,并使用AtomicReference
的set
方法来修改引用指向的对象,可以在Lambda表达式中正确地更新excels
列表,同时避免了编译错误。最后,您可以通过AtomicReference
的get
方法获取最终的excels
列表。