分布式锁案例

由于给定内容为空,暂无法提供包含关键信息的摘要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1案例说明

 

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FlyingFlowerV1Vo insert(FlyingFlowerReq flyingFlowerReq, String userId) throws Exception {
        //对进来的用户加锁
        RLock userLock = redissonClient.getLock(RedissonKey.USER_ID + userId);
        try{
            //尝试加锁, 最多等待1秒, 1000秒后自动解锁
            boolean getUserLock = userLock.tryLock(1, 1000, TimeUnit.MILLISECONDS);
            if (getUserLock) {
                //业务逻辑的代码,通常在插入修改的操作方法上进行加锁
        }catch (Exception e){
            //提示
            System.out.println("接令频繁"+ userId);
            throw new ResultInfo(ResultUtils.error("接令频繁,请稍后再试"));
        }finally {
            //解锁
            if (userLock.isLocked()) {
                if (userLock.isHeldByCurrentThread()) {
                    userLock.unlock();
                }
            }
        }
        return null;
    }

 

2.实际应用案例
import com.alibaba.cloud.commons.io.FileUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.kingtechfin.ktfcp.common.constant.BusinessConstants;
import com.kingtechfin.ktfcp.common.constant.PageConst;
import com.kingtechfin.ktfcp.common.entity.dto.ParamPageDto;
import com.kingtechfin.ktfcp.common.threadutils.ThreadRequestUtils;
import com.kingtechfin.ktfcp.common.utils.DateUtil;
import com.kingtechfin.ktfcp.common.utils.StringUtils;
import com.kingtechfin.ktfcp.framework.common.exception.BusinessException;
import com.kingtechfin.ktfcp.framework.common.utils.ClassInjectionUtils;
import com.kingtechfin.ktfcp.framework.common.utils.RedisLockUtils;
import com.kingtechfin.ktfcp.sif.pdm.infrastructure.constant.PdmConstant;
import com.kingtechfin.ktfcp.sif.pdm.infrastructure.constant.PdmRedisLockKeyConstant;
import com.kingtechfin.ktfcp.sif.pdm.infrastructure.enums.withhold.*;
import com.kingtechfin.ktfcp.sif.pdm.withhold.entity.po.PdmWithholdBatchItemTPO;
import com.kingtechfin.ktfcp.sif.pdm.withhold.entity.po.PdmWithholdBatchTPO;
import com.kingtechfin.ktfcp.sif.pdm.withhold.handler.impl.asyn.PdmCodeRuleGeneratorEx;
import com.kingtechfin.ktfcp.sif.pdm.withhold.handler.impl.biz.PdmWithholdBaseHandlerImpl;
import com.kingtechfin.ktfcp.sif.pdm.withhold.handler.impl.task.PdmBankResultBathTaskHandlerImpl;
import com.kingtechfin.ktfcp.sif.pdm.withhold.handler.impl.task.PdmVerifyBathTaskHandlerImpl;
import com.kingtechfin.ktfcp.sif.pdm.withhold.handler.impl.task.PdmWithholdBathTaskHandlerImpl;
import com.kingtechfin.ktfcp.sif.pdm.withhold.handler.impl.task.PdmWithholdBathTaskUnLockHandlerImpl;
import com.kingtechfin.ktfcp.sif.pdm.withhold.interfaces.dto.cmd.PdmBatchWithholdParamDto;
import com.kingtechfin.ktfcp.sif.pdm.withhold.interfaces.dto.cmd.PdmWithholdCollectionDeductCmd;
import com.kingtechfin.ktfcp.sif.pdm.withhold.interfaces.dto.info.PdmWithholdBatchCollectionInfoVo;
import com.kingtechfin.ktfcp.sif.pdm.withhold.interfaces.dto.info.PdmWithholdBatchInfoView;
import com.kingtechfin.ktfcp.sif.pdm.withhold.interfaces.dto.info.PdmWithholdCollectionViewDto;
import com.kingtechfin.ktfcp.sif.pdm.withhold.interfaces.dto.qry.PdmWithholdBatchCollectionPageQry;
import com.kingtechfin.ktfcp.sif.pdm.withhold.interfaces.dto.qry.PdmWithholdBatchPageQry;
import com.kingtechfin.ktfcp.sif.pdm.withhold.interfaces.dto.qry.PdmWithholdCollectionPageQry;
import com.kingtechfin.ktfcp.sif.pdm.withhold.service.IPdmWithholdBatchItemTableService;
import com.kingtechfin.ktfcp.sif.pdm.withhold.service.IPdmWithholdBatchTableService;
import com.kingtechfin.sif.calculator.param.dto.config.CalculateConfigBean;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@RequiredArgsConstructor
public class PdmWithholdBankTaskExHandlerImpl {


    private final RedissonClient redissonClient;
    private final RedisLockUtils redisLockUtils;
    private final PdmWithholdBaseHandlerImpl pdmWithholdBaseHandler;
    private final PdmWithholdCollectionHandlerImpl pdmWithholdCollectionHandlerImpl;
    private final PdmCodeRuleGeneratorEx pdmCodeRuleGeneratorEx;
    private final PdmWithholdBathTaskUnLockHandlerImpl pdmWithholdBathTaskUnLockHandlerImpl;
    private final PdmWithholdBatchTableHandlerImpl pdmWithholdBatchTableHandler;
    private final PdmWithholdBankTaskHandlerImpl pdmWithholdBankTaskHandlerImpl;
    private final IPdmWithholdBatchItemTableService pdmWithholdBatchItemTableService;
    private final IPdmWithholdBatchTableService pdmWithholdBatchTableService;

    public String queryBatchWithholdLockedDate() {
        List<PdmWithholdBatchCollectionInfoVo> pdmWithholdCollectionViewDtoList = pdmWithholdBatchTableHandler.queryBatchWithholdLockedDate();
        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.append("卡扣锁定合同款项信息:");
        if (Objects.nonNull(pdmWithholdCollectionViewDtoList) && !pdmWithholdCollectionViewDtoList.isEmpty()) {
            stringBuilder.append("\n");
            for (PdmWithholdBatchCollectionInfoVo pdmWithholdBatchCollectionInfoVo : pdmWithholdCollectionViewDtoList) {
                stringBuilder.append("合同编号:")
                        .append(pdmWithholdBatchCollectionInfoVo.getContractNo())
                        .append(" ")
                        .append("款项金额:")
                        .append(pdmWithholdBatchCollectionInfoVo.getCollectionAmt())
                        .append(" ")
                        .append("剩余应收:")
                        .append(pdmWithholdBatchCollectionInfoVo.getWithholdAmtShd())
                        .append("\n");
            }
        } else {
            stringBuilder.append("无");
        }

        return stringBuilder.toString();
    }

    public Boolean batchWithholdIsComplete() {
        RLock lock = redissonClient.getLock(PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_WITHHOLD);
        return !lock.isLocked();
    }

    /**
     * 1.跑批分布式锁,防止多次跑批
     * 2.搜索所有需要卡扣款项
     * 3.按银行类型合同编号分组
     * 4.按参数如2000笔款项一个批次分组,如果有跨2000的合同分配到下组
     * 5.启动多线程,主线程等待
     * 6.各个线程开启卡扣事务
     * 7.一个线程一个批次,开始跑页面卡扣逻辑
     * 8.各个线程提交成功或失败事务
     * 9.释放跑批分布式锁
     */
    public Boolean batchWithhold(PdmBatchWithholdParamDto batchWithholdParamDto) {

        if (Objects.isNull(batchWithholdParamDto)) {
            batchWithholdParamDto = new PdmBatchWithholdParamDto();
        }

        if (StringUtils.isEmpty(batchWithholdParamDto.getWithholdType())
                || (!PdmWithholdTypeEnum.PART_WITHHOLD.getState().equals(batchWithholdParamDto.getWithholdType())
                && !PdmWithholdTypeEnum.FULL_WITHHOLD.getState().equals(batchWithholdParamDto.getWithholdType()))) {
            batchWithholdParamDto.setWithholdType(PdmWithholdTypeEnum.PART_WITHHOLD.getState());
        }

        if (Objects.isNull(batchWithholdParamDto.getEachMaxCount())) {
            batchWithholdParamDto.setEachMaxCount(CalculateConfigBean.getConfig().getRequestFileMaxSize());
        }

        boolean threadPoolIsOk = false;
        boolean ret = false;
        // 1.跑批分布式锁,防止多次跑批
        RLock lock = redissonClient.getLock(PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_WITHHOLD);
        try {
            ret = lock.tryLock(PdmRedisLockKeyConstant.LOCK_TIME_WAIT, PdmRedisLockKeyConstant.LOCK_TIME * 2, TimeUnit.SECONDS);
            if (ret) {
                // 2.搜索所有需要卡扣款项
                PdmWithholdCollectionPageQry paramPageDto = new PdmWithholdCollectionPageQry();
                if (StringUtils.isNotEmpty(batchWithholdParamDto.getBankName())) {
                    paramPageDto.setBankName(batchWithholdParamDto.getBankName());
                }

                if (StringUtils.isNull(batchWithholdParamDto.getFundType())) {
                    paramPageDto.setCollectionType(BusinessConstants.COLLECTION_RENT);
                } else if (!"all".equalsIgnoreCase(batchWithholdParamDto.getFundType())){
                    paramPageDto.setCollectionType(batchWithholdParamDto.getFundType());
                }

                List<PdmWithholdCollectionViewDto> collectionDtos = pdmWithholdBaseHandler.queryCanWithholdCashFlowCollectionPage(paramPageDto);
                // 3.按银行类型合同套ID分组
                if (Objects.nonNull(collectionDtos) && !collectionDtos.isEmpty()) {
                    // 锁定合同信息
                    List<PdmWithholdBatchCollectionInfoVo> pdmWithholdCollectionViewDtoList = pdmWithholdBatchTableHandler.queryBatchWithholdLockedDate();
                    Map<String, PdmWithholdBatchCollectionInfoVo> lockedConInfoMap = new HashMap<>();
                    if (Objects.nonNull(pdmWithholdCollectionViewDtoList) && !pdmWithholdCollectionViewDtoList.isEmpty()) {
                        for (PdmWithholdBatchCollectionInfoVo pdmWithholdBatchCollectionInfoVo : pdmWithholdCollectionViewDtoList) {
                            lockedConInfoMap.put(pdmWithholdBatchCollectionInfoVo.getContractNo(), pdmWithholdBatchCollectionInfoVo);
                        }
                    }

                    // <银行名称, <合同套ID, List<款项ID>>
                    Map<String, Integer> conPenalCountMap = new HashMap<>();
                    Map<String, Map<String, List<String>>> groupFundMap = new HashMap<>();
                    for (PdmWithholdCollectionViewDto fund : collectionDtos) {
                        if (!lockedConInfoMap.isEmpty() && lockedConInfoMap.containsKey(fund.getContractNo())) {
                            continue;
                        }

                        Map<String, List<String>> groupBankMap = groupFundMap.get(fund.getBankName());
                        if (Objects.isNull(groupBankMap)) {
                            groupBankMap = new HashMap<>();
                            groupFundMap.put(fund.getBankName(), groupBankMap);
                        }

                        List<String> groupcConBundleIdList = groupBankMap.get(fund.getConBundleId());
                        if (Objects.isNull(groupcConBundleIdList)) {
                            groupcConBundleIdList = new ArrayList<>();
                            groupBankMap.put(fund.getConBundleId(), groupcConBundleIdList);
                        }

                        groupcConBundleIdList.add(fund.getCollectionId());
                        if (StringUtils.isNotEmpty(fund.getPenalCollectionId()) && !fund.getCollectionId().equals(fund.getPenalCollectionId())) {
                            groupcConBundleIdList.add(fund.getPenalCollectionId());

                            Integer count = conPenalCountMap.get(fund.getConBundleId());
                            if (Objects.isNull(count)) {
                                count = 0;
                            }
                            conPenalCountMap.put(fund.getConBundleId(), ++count);
                        }
                    }

                    // 4.按参数如2000笔款项一个批次分组,如果有跨2000的合同分配到下组
                    int batchMaxCount = batchWithholdParamDto.getEachMaxCount();
                    int groupNum = 0;
                    Map<Integer, Integer> batchPenalCountMap = new HashMap<>();
                    Map<String, Map<Integer, List<String>>> groupFundBatchMap = new HashMap<>();
                    for (Map.Entry<String, Map<String, List<String>>> groupFundBankMapEntry : groupFundMap.entrySet()) {
                        Map<Integer, List<String>> groupFundBankMap = groupFundBatchMap.get(groupFundBankMapEntry.getKey());
                        if (Objects.isNull(groupFundBankMap)) {
                            groupFundBankMap = new HashMap<>();
                            groupFundBatchMap.put(groupFundBankMapEntry.getKey(), groupFundBankMap);
                        }

                        List<String> conBundleList = new ArrayList<>(groupFundBankMapEntry.getValue().keySet());
                        Collections.shuffle(conBundleList);

                        List<String> batchList = new ArrayList<>();
                        int conPenalCountBatch = 0;
                        for (String conBundle : conBundleList) {
                            Integer conPenalCount = conPenalCountMap.get(conBundle);
                            if (Objects.isNull(conPenalCount)) {
                                conPenalCount = 0;
                            }

                            conPenalCountBatch += conPenalCount;

                            List<String> groupFundConBundleList = groupFundBankMapEntry.getValue().get(conBundle);
                            int count = batchList.size() + groupFundConBundleList.size() - conPenalCountBatch;
                            if (count > batchMaxCount) {
                                batchPenalCountMap.put(groupNum, conPenalCountBatch - conPenalCount);
                                groupFundBankMap.put(groupNum++, batchList);
                                conPenalCountBatch = conPenalCount;
                                batchList = new ArrayList<>();
                            }
                            batchList.addAll(groupFundConBundleList);
                        }
                        batchPenalCountMap.put(groupNum, conPenalCountBatch);
                        groupFundBankMap.put(groupNum++, batchList);
                    }

                    if (groupNum > 0) {
                        List<String> batchNoList = pdmCodeRuleGeneratorEx.querySyncBatchCodeByKey(PdmConstant.WITHHOLD_BATCH_ABC_REQ_NO, groupNum, 60, 60);
                        List<String> batchItemNoList = pdmCodeRuleGeneratorEx.querySyncBatchCodeByKey(PdmConstant.WITHHOLD_BATCH_ITEM_NO_KEY, collectionDtos.size(), 60, 60);

                        // 5.启动多线程,主线程等待
                        ThreadRequestUtils threadRequestUtils = new ThreadRequestUtils();
                        Integer withholdThreadCount = CalculateConfigBean.getConfig().getWithholdThreadCount();
                        threadRequestUtils.initThread(withholdThreadCount);
                        List<Runnable> cmd = new ArrayList<>();
                        int indexStart = 0;
                        int indexEnd = 0;
                        for (Map.Entry<String, Map<Integer, List<String>>> groupFundBatchEntry : groupFundBatchMap.entrySet()) {
                            for (Map.Entry<Integer, List<String>> batchEntry : groupFundBatchEntry.getValue().entrySet()) {
                                PdmWithholdCollectionDeductCmd pdmWithholdCollectionDeductCmd = new PdmWithholdCollectionDeductCmd();
                                pdmWithholdCollectionDeductCmd.setBatchNo(batchNoList.get(batchEntry.getKey()));
                                pdmWithholdCollectionDeductCmd.setCollectionIds(batchEntry.getValue());
                                pdmWithholdCollectionDeductCmd.setWithholdType(batchWithholdParamDto.getWithholdType());
                                Integer batchPenalCount = batchPenalCountMap.get(batchEntry.getKey());
                                if (Objects.isNull(batchPenalCount)) {
                                    batchPenalCount = 0;
                                }
                                indexEnd = indexStart + batchEntry.getValue().size() - batchPenalCount;
                                pdmWithholdCollectionDeductCmd.setBatchItemNo(batchItemNoList.subList(indexStart, indexEnd));
                                pdmWithholdCollectionDeductCmd.setIsBatchFlag(true);
                                indexStart = indexEnd;
                                PdmWithholdBathTaskHandlerImpl pdmWithholdBathTaskHandler =
                                        new PdmWithholdBathTaskHandlerImpl(
                                                threadRequestUtils.getContext(),
                                                pdmWithholdCollectionHandlerImpl,
                                                pdmWithholdCollectionDeductCmd,
                                                redisLockUtils);
                                cmd.add(pdmWithholdBathTaskHandler);
                            }
                        }

                        // 6.各个线程开启卡扣事务
                        // 7.一个线程一个批次,开始跑页面卡扣逻辑
                        // 8.各个线程提交成功或失败事务
                        List<Future<?>> futureList = threadRequestUtils.submits(cmd);
                        threadPoolIsOk = true;
                        pdmWithholdBathTaskUnLockHandlerImpl.waitThreadPoolAndUnlock(
                                "多线程异步卡扣",
                                threadRequestUtils,
                                futureList,
                                PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_WITHHOLD);
                    }
                }
            } else {
                throw new BusinessException("卡扣中,请稍后!");
            }
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
            throw new BusinessException("卡扣失败!");
        } finally {
            // 9.释放跑批分布式锁
            if (!threadPoolIsOk && ret && lock.isLocked()) {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }
        return ret;
    }

    public Boolean batchQueryBankResult() {
        boolean threadPoolIsOk = false;
        boolean ret = false;
        // 1.跑批分布式锁,防止多次跑批
        RLock lock = redissonClient.getLock(PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_BANK_RESULT);
        try {
            ret = lock.tryLock(PdmRedisLockKeyConstant.LOCK_TIME_WAIT, PdmRedisLockKeyConstant.LOCK_TIME, TimeUnit.SECONDS);
            if (ret) {
                ParamPageDto<PdmWithholdBatchPageQry> entityDto = ParamPageDto.build();
                entityDto.setPageSize(PageConst.PAGE_MAX_SIZE);
                PdmWithholdBatchPageQry pdmWithholdBatchPageQry = new PdmWithholdBatchPageQry();
                pdmWithholdBatchPageQry.setSysCtimeStart(DateUtil.getTodayStartTs());
                pdmWithholdBatchPageQry.setSysCtimeEnd(DateUtil.getTodayFrontOrBackStartTime(1) - 1);
                entityDto.setDto(pdmWithholdBatchPageQry);
                IPage<PdmWithholdBatchInfoView> pageDatas = pdmWithholdBatchTableHandler.batchPage(entityDto);

                if (Objects.nonNull(pageDatas) && Objects.nonNull(pageDatas.getRecords()) && !pageDatas.getRecords().isEmpty()) {
                    List<PdmWithholdBatchInfoView> pdmWithholdBatchPageQryList = pageDatas.getRecords();

                    pdmWithholdBatchPageQryList.removeIf(pdmWithholdBatchInfoView -> !PdmWithholdBatchStateEnum.REQ_SUCCESS.getState().equals(pdmWithholdBatchInfoView.getBatchState())
                            && !PdmWithholdBatchStateEnum.REQ_FAIL.getState().equals(pdmWithholdBatchInfoView.getBatchState())
                            && !PdmWithholdBatchStateEnum.BATCH_HANDLING.getState().equals(pdmWithholdBatchInfoView.getBatchState())
                            && !PdmWithholdBatchStateEnum.BATCH_HANDLE_FAIL.getState().equals(pdmWithholdBatchInfoView.getBatchState()));
                    // 5.启动多线程,主线程等待
                    ThreadRequestUtils threadRequestUtils = new ThreadRequestUtils();
                    Integer bankResultThreadCount = CalculateConfigBean.getConfig().getBankResultThreadCount();
                    threadRequestUtils.initThread(bankResultThreadCount);
                    List<Runnable> cmd = new ArrayList<>();

                    for (PdmWithholdBatchInfoView pdmWithholdBatchInfoView : pdmWithholdBatchPageQryList) {
                        PdmBankResultBathTaskHandlerImpl pdmBankResultBathTaskHandlerImpl =
                                new PdmBankResultBathTaskHandlerImpl(
                                        threadRequestUtils.getContext(),
                                        pdmWithholdBankTaskHandlerImpl,
                                        pdmWithholdBatchInfoView.getId(),
                                        redisLockUtils);
                        cmd.add(pdmBankResultBathTaskHandlerImpl);
                    }

                    // 6.各个线程开启卡扣事务
                    // 7.一个线程一个批次,开始跑页面卡扣逻辑
                    // 8.各个线程提交成功或失败事务
                    List<Future<?>> futureList = threadRequestUtils.submits(cmd);
                    threadPoolIsOk = true;
                    pdmWithholdBathTaskUnLockHandlerImpl.waitThreadPoolAndUnlock(
                            "多线程异步回盘",
                            threadRequestUtils,
                            futureList,
                            PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_BANK_RESULT);

                }
            } else {
                throw new BusinessException("回盘中,请稍后!");
            }
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
            throw new BusinessException("回盘失败!");
        } finally {
            // 9.释放跑批分布式锁
            if (!threadPoolIsOk && ret && lock.isLocked()) {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }

        return ret;
    }

    public Boolean batchQueryBankResultIsComplete() {
        RLock lock = redissonClient.getLock(PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_BANK_RESULT);
        return !lock.isLocked();
    }

    public Boolean batchVerify() {
        boolean threadPoolIsOk = false;
        boolean ret = false;
        // 1.跑批分布式锁,防止多次跑批
        RLock lock = redissonClient.getLock(PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_VERIFY);
        try {
            ret = lock.tryLock(PdmRedisLockKeyConstant.LOCK_TIME_WAIT, PdmRedisLockKeyConstant.LOCK_TIME, TimeUnit.SECONDS);
            if (ret) {
                ParamPageDto<PdmWithholdBatchCollectionPageQry> entityDto = ParamPageDto.build();
                entityDto.setPageSize(PageConst.PAGE_MAX_SIZE);
                PdmWithholdBatchCollectionPageQry pdmWithholdBatchCollectionPageQry = new PdmWithholdBatchCollectionPageQry();
                pdmWithholdBatchCollectionPageQry.setWithholdState(PdmWithholdStateEnum.WITHHOLD_SUCCESS.getState());
                pdmWithholdBatchCollectionPageQry.setVerifyStates(
                        Arrays.asList(PdmWithholdVerifyStateEnum.VERIFY_DEFAULT.getState(),
                                PdmWithholdVerifyStateEnum.VERIFY_ZERO.getState(),
                                PdmWithholdVerifyStateEnum.VERIFY_FAIL.getState(),
                                PdmWithholdVerifyStateEnum.VERIFY_PART.getState()
                        ));
                pdmWithholdBatchCollectionPageQry.setReturnState(PdmWithholdReturnStateEnum.DEFAULT.getCode());
                pdmWithholdBatchCollectionPageQry.setRecoilState(BusinessConstants.BUSINESS_NO);
                pdmWithholdBatchCollectionPageQry.setWithholdTimeStart(DateUtil.getTodayStartTs());
                pdmWithholdBatchCollectionPageQry.setWithholdTimeEnd(DateUtil.getTodayFrontOrBackStartTime(1) - 1);
                entityDto.setDto(pdmWithholdBatchCollectionPageQry);
                IPage<PdmWithholdBatchCollectionInfoVo> pageDatas = pdmWithholdBatchTableHandler.withholdCollectionPage(entityDto);

                if (Objects.nonNull(pageDatas) && Objects.nonNull(pageDatas.getRecords()) && !pageDatas.getRecords().isEmpty()) {
                    List<PdmWithholdBatchCollectionInfoVo> pdmWithholdBatchCollectionInfoVoList = pageDatas.getRecords();

                    // 按批次,按合同套ID数分组 Map<批次编号,Map<合同套ID,List<核销列表>>>
                    Map<String, Map<String, List<PdmWithholdBatchCollectionInfoVo>>> groupFundMap = new HashMap<>();
                    for (PdmWithholdBatchCollectionInfoVo withHoldFund : pdmWithholdBatchCollectionInfoVoList) {
                        Map<String, List<PdmWithholdBatchCollectionInfoVo>> groupBatchNoMap = groupFundMap.get(withHoldFund.getBatchNo());
                        if (Objects.isNull(groupBatchNoMap)) {
                            groupBatchNoMap = new HashMap<>();
                            groupFundMap.put(withHoldFund.getBatchNo(), groupBatchNoMap);
                        }

                        List<PdmWithholdBatchCollectionInfoVo> groupcConBundleIdList = groupBatchNoMap.get(withHoldFund.getConBundleId());
                        if (Objects.isNull(groupcConBundleIdList)) {
                            groupcConBundleIdList = new ArrayList<>();
                            groupBatchNoMap.put(withHoldFund.getConBundleId(), groupcConBundleIdList);
                        }

                        groupcConBundleIdList.add(withHoldFund);
                    }

                    Integer batchVerifyMaxSize = CalculateConfigBean.getConfig().getBatchVerifyMaxSize();
                    int groupNum = 0;
                    // 按批次,按合同套ID数分组 Map<批次编号,Map<合同套ID,List<核销列表>>>
                    Map<String, Map<Integer, List<PdmWithholdBatchCollectionInfoVo>>> groupFundBatchMap = new HashMap<>();
                    for (Map.Entry<String, Map<String, List<PdmWithholdBatchCollectionInfoVo>>> groupFundBatchMapEntry : groupFundMap.entrySet()) {
                        Map<Integer, List<PdmWithholdBatchCollectionInfoVo>> groupFundBatchNoMap = groupFundBatchMap.get(groupFundBatchMapEntry.getKey());
                        if (Objects.isNull(groupFundBatchNoMap)) {
                            groupFundBatchNoMap = new HashMap<>();
                            groupFundBatchMap.put(groupFundBatchMapEntry.getKey(), groupFundBatchNoMap);
                        }

                        List<PdmWithholdBatchCollectionInfoVo> conBundleList = new ArrayList<>();
                        for (Map.Entry<String, List<PdmWithholdBatchCollectionInfoVo>> groupFundConBundleMapEntry : groupFundBatchMapEntry.getValue().entrySet()) {
                            int count = conBundleList.size() + groupFundConBundleMapEntry.getValue().size();
                            if (count > batchVerifyMaxSize) {
                                groupFundBatchNoMap.put(groupNum++, conBundleList);
                                conBundleList = new ArrayList<>();
                            }

                            conBundleList.addAll(groupFundConBundleMapEntry.getValue());
                        }
                        groupFundBatchNoMap.put(groupNum++, conBundleList);
                    }

                    // 5.启动多线程,主线程等待
                    ThreadRequestUtils threadRequestUtils = new ThreadRequestUtils();
                    Integer verifyThreadCount = CalculateConfigBean.getConfig().getVerifyThreadCount();
                    threadRequestUtils.initThread(verifyThreadCount);
                    List<Runnable> cmd = new ArrayList<>();

                    for (Map.Entry<String, Map<Integer, List<PdmWithholdBatchCollectionInfoVo>>> groupFundBatchEntry : groupFundBatchMap.entrySet()) {
                        for (Map.Entry<Integer, List<PdmWithholdBatchCollectionInfoVo>> batchEntry : groupFundBatchEntry.getValue().entrySet()) {
                            PdmVerifyBathTaskHandlerImpl pdmVerifyBathTaskHandlerImpl =
                                    new PdmVerifyBathTaskHandlerImpl(
                                            threadRequestUtils.getContext(),
                                            pdmWithholdBatchTableHandler,
                                            groupFundBatchEntry.getKey(),
                                            batchEntry.getValue(),
                                            redisLockUtils);
                            cmd.add(pdmVerifyBathTaskHandlerImpl);
                        }
                    }
                    // 6.各个线程开启卡扣事务
                    // 7.一个线程一个批次,开始跑页面卡扣逻辑
                    // 8.各个线程提交成功或失败事务
                    List<Future<?>> futureList = threadRequestUtils.submits(cmd);
                    threadPoolIsOk = true;
                    pdmWithholdBathTaskUnLockHandlerImpl.waitThreadPoolAndUnlock(
                            "多线程异步核销",
                            threadRequestUtils,
                            futureList,
                            PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_VERIFY);
                }
            } else {
                throw new BusinessException("核销中,请稍后!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new BusinessException("核销失败!");
        } finally {
            // 9.释放跑批分布式锁
            if (!threadPoolIsOk && ret && lock.isLocked()) {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }

        return ret;
    }

    public Boolean batchVerifyIsComplete() {
        RLock lock = redissonClient.getLock(PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_VERIFY);
        return !lock.isLocked();
    }

    public Boolean batchWithholdAndBankResultAndVerifyIsComplete() {
        RLock lockWithhold = redissonClient.getLock(PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_WITHHOLD);
        RLock lockBankResult = redissonClient.getLock(PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_BANK_RESULT);
        RLock lockVerify = redissonClient.getLock(PdmRedisLockKeyConstant.PDM_WITHHOLD_HANDLE_DEDUCT_LOCK_VERIFY);
        return !lockWithhold.isLocked() && !lockBankResult.isLocked() && !lockVerify.isLocked();
    }

    public boolean addWithholdDataFromJson(String path) {
        // 读取Json文件中的数据
        try {
            //读取文件
            File filePath = new File(path);
            String input = FileUtils.readFileToString(filePath, "UTF-8");
            PdmWithholdBatchTPO saveToDbBatchDto = JSONObject.parseObject(input, PdmWithholdBatchTPO.class);
            pdmWithholdBatchTableService.save(saveToDbBatchDto);
            List<PdmWithholdBatchItemTPO> batchItemTPOS = ClassInjectionUtils.convertList2List(saveToDbBatchDto.getBatchItemDtos(), PdmWithholdBatchItemTPO.class);
            pdmWithholdBatchItemTableService.insertBatchSif(batchItemTPOS, false, CalculateConfigBean.getConfig().getBatchWithHoldMaxSize());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值