Java 使用线程池和CountDownLatch分批插入或者更新数据

  需求:在开发业务报表时,需要从MySQL数据库读取数据后进行操作,然后写入数据库,使用定时任务跑批。

  分析:①兼顾性能,②  MySQL没有Oracle那么方便、强大的存储过程。综上所述,使用线程池以分批提交的方案把数据插入MySQL数据库,对于更新操作、在Java端进行分页等的操作,本方案也支持。代码如下:

 

/**
 * 分页操作数据
 */
@Slf4j
@Component
public class BatchDealDemo  {

    private void batchDeal(List data, int batchNum) throws InterruptedException {
        int totalNum = data.size();
        int pageNum = totalNum % batchNum == 0 ? totalNum / batchNum : totalNum / batchNum + 1;
        ExecutorService executor = Executors.newFixedThreadPool(pageNum);
        log.info("主线程开始执行 begin --- ");

        try {
            CountDownLatch countDownLatch = new CountDownLatch(pageNum);
            List subData = null;
            int fromIndex, toIndex;
            for (int i = 0; i < pageNum; i++) {
                fromIndex = i * batchNum;
                toIndex = Math.min(totalNum, fromIndex + batchNum);
                subData = data.subList(fromIndex, toIndex);
                ImportTask task = new ImportTask(subData, countDownLatch);
                executor.execute(task);
            }
            // 当前线程必须在执行完任务之后立即调用CountDownLatch.await()方法,
            // 这样主线程的操作就会被阻塞,直到全部子线程完成各自的任务。
            //  CountDownLatch类中计数器的值等于0时,主线程就能通过await()方法恢复执行自己的任务。
            countDownLatch.await();
            log.info("数据操作完成!可以在此开始主线程的其它业务");
            log.info("主线程执行完毕 end --- ");
        } finally {
            // 关闭线程池,释放资源
            executor.shutdown();
        }
    }

    class ImportTask implements Runnable {
        private List list;
        private CountDownLatch countDownLatch;

        public ImportTask(List data, CountDownLatch countDownLatch) {
            this.list = data;
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            if (null != list) {
                // 业务逻辑,例如批量insert或者update
                log.info("现在操作的数据是{}", list);
            }
            // 发出子线程任务完成的信号
            countDownLatch.countDown();
        }
    }
}

 

 

  在第1行中,List data表示传入的数据,batchNum表示每一次处理的数量,例如500条等。

 

posted @ 2019-05-31 07:05  楼兰胡杨  阅读(15242)  评论(0编辑  收藏  举报