多线程处理大量数据

一、背景

最近在在建设银行代发功能,需要批量处理代发数据,线性处理效率比较低,大概1秒钟一条数据;然后考虑用多线程处理。刚开始使用的是Executors.newFixedThreadPool(10)这种方式创建固定数量线程池;后面考虑到数据量大的时候,可能队列装不下,导致异常,然后换成了ExecutorService executorSer = new ThreadPoolExecutor(10,30,10,TimeUnit.SECONDS, new LinkedBlockingDeque<>(2000),new ThreadPoolExecutor.CallerRunsPolicy());

二、代码

CountDownLatch latch = new CountDownLatch(10);
ExecutorService executorSer = new ThreadPoolExecutor(10,30,10,TimeUnit.SECONDS, new LinkedBlockingDeque<>(2000),new ThreadPoolExecutor.CallerRunsPolicy());
for (ZfPayrollBatchRecDO batchRecDO:zfPayrollBatchRecDOS){
	executorSer.execute(new PayRollBatchRunnable(latch, batchRecDO, tyPubSysParamCacheClient, dsk075Service, zfPayrollBatchRecService, zfPayrollBatchIntfRecService, dsk074Service));
}
latch.wait();
executorSer.shutdown();
public class PayRollBatchRunnable implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(PayRollBatchRunnable.class);

    private ZfPayrollBatchService zfPayrollBatchService;

    private ZfPayrollBatchRecService zfPayrollBatchRecService;

    private DSK075Service dsk075Service;

    private DSK074Service dsk074Service;

    private ZfPayrollBatchIntfRecService zfPayrollBatchIntfRecService;

    private TyPubSysParamCacheClient tyPubSysParamCacheClient;

    private final CountDownLatch latch;

    private final ZfPayrollBatchRecDO batchRecDO;

    public PayRollBatchRunnable(CountDownLatch latch,ZfPayrollBatchRecDO batchRecDO,TyPubSysParamCacheClient client,DSK075Service dsk075Service,ZfPayrollBatchRecService zfPayrollBatchRecService,ZfPayrollBatchIntfRecService zfPayrollBatchIntfRecService,DSK074Service dsk074Service){
        this.latch = latch;
        this.batchRecDO = batchRecDO;
        this.tyPubSysParamCacheClient = client;
        this.dsk075Service = dsk075Service;
        this.dsk074Service = dsk074Service;
        this.zfPayrollBatchRecService = zfPayrollBatchRecService;
        this.zfPayrollBatchIntfRecService = zfPayrollBatchIntfRecService;
    }

    @Override
    public void run() {
        try {
            doWork(this.batchRecDO);
            logger.info("当前代发处理信息:{}",JSON.toJSONString(batchRecDO));
            latch.countDown();
        } catch (Exception ex) {
            logger.info("异常信息:{}",ex.getMessage());
        }
    }

    public void doWork(ZfPayrollBatchRecDO batchRecDO) {
        logger.info("work开始处理");
        //2.代发完成后修改-代发业务文件批次表处理状态
        DSK074Vo dsk074Vo = new DSK074Vo();
        dsk074Vo.setAmount(batchRecDO.getTranAmt().toString());
        dsk074Vo.setCorpSerno(batchRecDO.getCorpSerNo());//前置请求流水号
        dsk074Vo.setRecSvcID(batchRecDO.getSvcId());
        dsk074Vo.setRecCstAccNo(batchRecDO.getCstAccNo());
        dsk074Vo.setTrdPCstAccNo(tyPubSysParamCacheClient.getParamValue("CCB_THRD_PLAT_CST_ACC_NO","44201501100056411087"));//代发第三方平台账号
        long startTime = System.currentTimeMillis();
        DSK074Res dsk074Res = dsk074Service.dsk074(dsk074Vo);
        long endTime =  System.currentTimeMillis();
        long  intfExeTime = endTime - startTime;
        boolean incRetFlag = false;//接口调用成功标识
        if ("0000".equals(dsk074Res.getReturnCode())){
            //代发业务批次流水表记录状态
            ZfPayrollBatchRecDO zfPayrollBatchRecDO = new ZfPayrollBatchRecDO();
            zfPayrollBatchRecDO.setBtcId(batchRecDO.getBtcId());
            zfPayrollBatchRecDO.setSeqNo(batchRecDO.getSeqNo());
            zfPayrollBatchRecDO.setDealStatus("1");//处理状态:0:待处理,1:处理成功,2:处理失败
            zfPayrollBatchRecDO.setEvtTraceId(dsk074Res.getSysEvtTraceId());
            try {
                zfPayrollBatchRecService.updateSelective(zfPayrollBatchRecDO);
            }catch (Exception  e){
                logger.error("代发业务批次流水表记录更新失败:{}",e.getMessage());
            }
            incRetFlag = true;
        }else {
            //如果失败,反查询下代发结果
            DSK075Vo dsk075Vo = new DSK075Vo();
            dsk075Vo.setOrigCorpSerno(batchRecDO.getCorpSerNo());
            DSK075Res dsk075Res = dsk075Service.dsk075(dsk075Vo);
            if ("0000".equals(dsk075Res.getReturnCode())){
                ZfPayrollBatchRecDO zfPayrollBatchRecDO = new ZfPayrollBatchRecDO();
                zfPayrollBatchRecDO.setBtcId(batchRecDO.getBtcId());
                zfPayrollBatchRecDO.setSeqNo(batchRecDO.getSeqNo());
                zfPayrollBatchRecDO.setDealStatus("1");//处理状态:0:待处理,1:处理成功,2:处理失败
                zfPayrollBatchRecDO.setEvtTraceId(dsk075Res.getSysEvtTraceId());
                try {
                    zfPayrollBatchRecService.updateSelective(zfPayrollBatchRecDO);
                }catch (Exception  e){
                    logger.error("代发业务批次流水表记录更新失败:{}",e.getMessage());
                }
                incRetFlag = true;
            }else {
                ZfPayrollBatchRecDO zfPayrollBatchRecDO = new ZfPayrollBatchRecDO();
                zfPayrollBatchRecDO.setBtcId(batchRecDO.getBtcId());
                zfPayrollBatchRecDO.setSeqNo(batchRecDO.getSeqNo());
                zfPayrollBatchRecDO.setDealStatus("2");//处理状态:0:待处理,1:处理成功,2:处理失败
                try {
                    zfPayrollBatchRecService.updateSelective(zfPayrollBatchRecDO);
                }catch (Exception  e){
                    logger.error("代发业务批次流水表记录更新失败:{}",e.getMessage());
                }
                incRetFlag = false;
            }

        }
        //新增代发接口调用记录
        ZfPayrollBatchIntfRecDO intfRecDO = new ZfPayrollBatchIntfRecDO();
        intfRecDO.setBtcId(batchRecDO.getBtcId());
        intfRecDO.setSeqNo(batchRecDO.getSeqNo());
        intfRecDO.setAcctDay(DateUtils.getCurrentDateNumber());
        intfRecDO.setInParam(JSON.toJSONString(dsk074Vo));
        intfRecDO.setOutParam(JSON.toJSONString(dsk074Res));
        intfRecDO.setAddTime(new Date());
        if (incRetFlag){
            intfRecDO.setIncRetFlag("1");//接口调用结果 0:未返回,1:返回成功,2:返回失败
        }else {
            intfRecDO.setIncRetFlag("2");//接口调用结果 0:未返回,1:返回成功,2:返回失败
        }
        intfRecDO.setIncRetCode(dsk074Res.getReturnCode());
        intfRecDO.setIncRetRemark(dsk074Res.getReturnMsg());
        intfRecDO.setEvtTraceId(dsk074Res.getSysEvtTraceId());
        intfRecDO.setIncCallNum(1);
        intfRecDO.setIncLastTime(new Date());
        intfRecDO.setIncExeTime(CallTimeUnit.getTimeUnit(intfExeTime));
        intfRecDO.setPartDate(DateUtils.getCurrentDateNumber());
        try {
            zfPayrollBatchIntfRecService.insertSelective(intfRecDO);
        }catch (Exception e){
            logger.error("代发调用接口记录失败:{}",e.getMessage());
        }

        logger.info("work结束处理");
    }
}

三、总结

        原本120条的数据,线性执行,需要将近120秒。差不多一秒一条数据;调整后,500条数据只需要12-14秒;多线程时真的强大。以后要多研究多线程,这个功能还是挺牛叉的?

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JAVA菜鸟程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值