多线程并行处理数据

多线程并行处理数据

在工作中很多时候会因为各种原因选择使用多线程并行去处理我们要处理的数据,前段时间工作中就遇到了需要多线程去处理的业务逻辑情况,记录一下。

业务场景

在后台系统代码中,首先会拿到一些条件,然后会根据入参组合成一个modelList,需要用modelList去循环远程调用第三方的系统,调用第三方系统执行速度很慢,调用一次需要1至2秒,modelList稍微长一点的时候就会出现循环调用占用时间太长的问题。

解决方法

使用多线程去并行调用第三方,多个接口同时调用,减少调用时间

部分逻辑代码


    @Autowired(required = false)
    private JedisPool jedisPool;

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;
    
	@Override
    public List<HisAppointmentSourceDTO> getAppointmentSourceByCondition(HisAppointmentSourceModel hisAppointmentSourceModel) {
        try {
            //定义调用his的modelList
            List<HisDocApptSourceModel> modelList = Lists.newArrayList();
            HisDocApptSourceModel hisDocApptSourceModel = HisDocApptSourceModel.builder().build();
            Integer latchSize = 0;
            //入参方式1: 医生部门Map,开始时间,结束时间
            if (null != hisAppointmentSourceModel.getDocMap() && !hisAppointmentSourceModel.getDocMap().isEmpty()){
                latchSize = hisAppointmentSourceModel.getDocMap().size();
                for (String docCode : hisAppointmentSourceModel.getDocMap().keySet()) {
                    hisDocApptSourceModel = HisDocApptSourceModel.builder().startDate(DateUtils.format(hisAppointmentSourceModel.getStartDate(),CommonConstant.YYYY_MM_DD)).endDate(DateUtils.format(hisAppointmentSourceModel.getEndDate(),CommonConstant.YYYY_MM_DD)).docCode(docCode).deptCode(hisAppointmentSourceModel.getDocMap().get(docCode)).build();
                    modelList.add(hisDocApptSourceModel);
                }
            }else if (!StringUtils.isEmpty(hisAppointmentSourceModel.getDeptCode())){
                if (!CollectionUtils.isEmpty(hisAppointmentSourceModel.getDoctorCodeList())){
                    //入参方式2: 部门code,医生codeList,开始时间,结束时间
                    latchSize = hisAppointmentSourceModel.getDoctorCodeList().size();
                    for (String docCode : hisAppointmentSourceModel.getDoctorCodeList()) {
                        hisDocApptSourceModel = HisDocApptSourceModel.builder().startDate(DateUtils.format(hisAppointmentSourceModel.getStartDate(),CommonConstant.YYYY_MM_DD)).endDate(DateUtils.format(hisAppointmentSourceModel.getEndDate(),CommonConstant.YYYY_MM_DD)).docCode(docCode).deptCode(hisAppointmentSourceModel.getDeptCode()).build();
                        modelList.add(hisDocApptSourceModel); }
                }else {
                    //入参方式3: 部门code,开始时间,结束时间
                    //查询该段时间的该部门下所有出诊医生
                    HisApptDocInfoModel model = HisApptDocInfoModel.builder().deptCode(hisAppointmentSourceModel.getDeptCode()).startDate(DateUtils.format(hisAppointmentSourceModel.getStartDate(),CommonConstant.YYYY_MM_DD)).endDate(DateUtils.format(hisAppointmentSourceModel.getEndDate(),CommonConstant.YYYY_MM_DD)).build();
                    List<HisApptDocInfoDTO> hisApptDocInfoDTOList = getApptDocInfo(model);
                    latchSize = hisApptDocInfoDTOList.size();
                    for (HisApptDocInfoDTO hisApptDocInfoDTO : hisApptDocInfoDTOList) {
                        hisDocApptSourceModel = HisDocApptSourceModel.builder().startDate(DateUtils.format(hisAppointmentSourceModel.getStartDate(),CommonConstant.YYYY_MM_DD)).endDate(DateUtils.format(hisAppointmentSourceModel.getEndDate(),CommonConstant.YYYY_MM_DD)).docCode(hisApptDocInfoDTO.getYsdm()).deptCode(hisAppointmentSourceModel.getDeptCode()).build();
                        modelList.add(hisDocApptSourceModel);
                    }
                }
            }
            CountDownLatch latch = new CountDownLatch(latchSize);
            List<CompletableFuture<List<AppointmentSourceDO>>> futures = Lists.newArrayList();
            List<AppointmentSourceDO> appointmentSourceDOList = Lists.newArrayList();
            //多线程并行调用his
            for (HisDocApptSourceModel model: modelList) {
                CompletableFuture<List<AppointmentSourceDO>> future = CompletableFuture.supplyAsync(() -> {
                    //调用his查询医生号源
                    List<HisDocApptSourceResponse> docApptSourceResponseList = hisServiceAdapter.getDocApptSource(model);
                    //筛选对应部门号源
                    List<AppointmentSourceDO> list = Lists.newArrayList();
                    for (HisDocApptSourceResponse hisDocApptSourceResponse : docApptSourceResponseList) {
                        if (hisDocApptSourceResponse.getKsdm().equals(model.getDeptCode())) {
                            AppointmentSourceDO appointmentSourceDO = buildeCommonDo(hisDocApptSourceResponse);
                            appointmentSourceDO.setDoctorCode(model.getDocCode());
                            list.add(appointmentSourceDO);
                        }
                    }
                    latch.countDown();
                    return list;
                }, threadPoolExecutor);
                futures.add(future);
            }
            latch.await(5, TimeUnit.SECONDS);
            // 再次汇总全量信息
            List<List<AppointmentSourceDO>> taskResults = futures.stream().map(CompletableFuture::join).collect(Collectors.toList());
            appointmentSourceDOList = taskResults.stream().flatMap(Collection::stream).collect(Collectors.toList());

            if (!CollectionUtils.isEmpty(appointmentSourceDOList)) {
                return appointmentSourceDOList.stream().map(appointmentSourceDO -> {
                    HisAppointmentSourceDTO hisAppointmentSourceDTO = HisAppointmentSourceDTO.builder().build();
                    BeanUtils.copyProperties(appointmentSourceDO, hisAppointmentSourceDTO);
                    return hisAppointmentSourceDTO;
                }).collect(Collectors.toList());
            } else {
                return new ArrayList<>();
            }
        }catch (Exception e){
            log.error("查询医生号源信息异常", e);
            return new ArrayList<>();
        }
    }

回顾

1:先根据各种入参方式拼装modelList。
2:创建泛型为CompletableFuture的List :futures ,用于存放每个线程执行拿到的结果。
3:循环modelList 创建CompletableFuture对象 future,拿到执行结果后添加到futures 中。
4:用futures汇总全部信息,做对象转换操作。
5:返回结果集。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ellis_li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值