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

发布于:2024-04-03 ⋅ 阅读:(119) ⋅ 点赞:(0)

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


    /**
     * 导出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 的 HashMap
        Map<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加一个value
                if ((i + 1) % 20 == 0) {//每20个清空
                    nbackListHashMap.put(Integer.parseInt(blockNum), nBlackJsonVOS);
                    nBlackJsonVOS = new ArrayList<>();
                }

            }

            //循环遍历我的map
            int 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();
                    // 获取当前轮的 blockNum
                    blockNum = Integer.parseInt(nBlackJsonVO.getBlockNum());
                    // 获取难度等级
                    difficultyLevel = Integer.parseInt(nBlackJsonVO.getLevel());

                    // 将反应时间转换为 BigDecimal
                    if (timer != null && !timer.isEmpty()) {
                        // 将字符串转换为 BigDecimal
                        BigDecimal 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 less
                String picType = jsonObject.getString("picType");//A or N
                String 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-100
				if (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 的 HashMap
        Map<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加一个value
                    if ((i + 1) % 20 == 0) {//每20个清空
                        nbackListHashMap.put(Integer.parseInt(blockNum), nBlackJsonVOS);
                        nBlackJsonVOS = new ArrayList<>();
                    }

                }

                //循环遍历我的map
                int 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();
                        // 获取当前轮的 blockNum
                        blockNum = Integer.parseInt(nBlackJsonVO.getBlockNum());
                        // 获取难度等级
                        difficultyLevel = Integer.parseInt(nBlackJsonVO.getLevel());

                        // 将反应时间转换为 BigDecimal
                        if (timer != null && !timer.isEmpty()) {
                            // 将字符串转换为 BigDecimal
                            BigDecimal 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 less
                    String picType = jsonObject.getString("picType");//A or N
                    String 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-100
                    if (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 的 HashMap
            Map<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列表。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到