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;
}
}