《代码干货》Quartz集合批量多线程处理

前言

我们经常使用spring quartz 处理各种业务,那么如何使用多线程批量处理,而且保证不会有重复数据。想必处理过这类业务的朋友,一定了解Executors或者ThreadPoolTaskExecutor这类工具。这里不对这些东西做任何解说。因为时间关系,我按自己的方式实现,直接提供代码供大家参考。

需要返值的
public class GameConsumerJob {
    private static final Logger logger = LoggerFactory.getLogger(GameConsumerJob.class);

    @Autowired
    private Service service;

    @Autowired
    private CxylThreadPool threadPool;

    static int threadCounts = 10;//使用的线程数
    static long sum = 0;

    public void execute() {
        logger.info("队列消费者线程运行,GameConsumerJob{}", Thread.currentThread().getName());
        try {
            pushQueueWorkerRun();
        } catch (Exception e) {
            logger.info("队列消费者线程运行,GameConsumerJob{}发生异常:", e);
        }
    }

    private void pushQueueWorkerRun() throws Exception {
        List<CxylConsumerData> dataList = service.getLastConsumers(2000);
        if (dataList != null && dataList.size() > 0) {
            ExecutorService ex = Executors.newFixedThreadPool(threadCounts);
            List<Callable<Long>> callList = new ArrayList<Callable<Long>>();
            int dataCount = dataList.size();
            int len = dataCount/threadCounts;//分批数
            if(len == 0){
                threadCounts = dataCount;//采用一个线程处理List中的一个元素
                len = 1;//重新平均分割List
            }
            for(int i=0; i<threadCounts; i++){
                final List<CxylConsumerData> subList;
                if(i == threadCounts-1){
                    subList = dataList.subList(i*len, dataCount);
                }else{
                    subList = dataList.subList(i*len, len*(i+1)>dataList.size()?dataList.size():len*(i+1));
                }
                //采用匿名内部类实现
                callList.add(new Callable<Long>(){
                    public Long call() throws Exception {
                        long subSum = 0L;
                        for(CxylConsumerData date : subList){
                            int value = cxylZdService.playerConsume(date);
                            subSum += value;
                        }
                        System.out.println("分配给线程:"+Thread.currentThread().getName()+"那一部分List的整数和为:\tSubSum:"+subSum);
                        return subSum;
                    }
                });
            }

            List<Future<Long>> futureList = ex.invokeAll(callList);
            for(Future<Long> future: futureList){
                sum += future.get();
            }
            ex.shutdown();
        }
    }

}
使用Callable存在性能消耗,尤其大量子线程创建,以下是无返值优化
    private void pushQueueWorkerRun2() throws Exception {
        List<CxylConsumerData> dataList = service.getLastConsumers(2000);
        if (dataList != null && dataList.size() > 0) {
            ExecutorService exe = Executors.newFixedThreadPool(threadCounts);
            int dataCount = dataList.size();
            int len = dataCount/threadCounts;//分批数
            if(len == 0){
                threadCounts = dataCount;//采用一个线程处理List中的一个元素
                len = 1;//重新平均分割List
            }
            for(int i=0; i<threadCounts; i++){
                final List<CxylConsumerData> subList;
                if(i == threadCounts-1){
                    subList = dataList.subList(i*len, dataCount);
                }else{
                    subList = dataList.subList(i*len, len*(i+1)>dataList.size()?dataList.size():len*(i+1));
                }
                Runnable run = new Runnable() {
                    @Override
                    public void run() {
                        for(CxylConsumerData date : subList){
                            cxylZdService.playerConsume(date);
                        }
                    }
                };
                exe.execute(run);
            }
            exe.shutdown();
            while (true) {
                if (exe.isTerminated()) {
                    logger.info("GameConsumerJob is end {}", Thread.currentThread().getName());
                    break;
                }
                Thread.sleep(200);
            }
            exe.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
        }
    }

以上代理仅供大家参考,实现的方式很多,根据自己的业务情况实现即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值