多线程使用:batchInsert

工具类中的用多线程做插入数据的方法

   /**400一组(按组开多线程),200一插
     * 使用map对象的key作为参数列表拼接sql
     * 动态构建添加参数列表以及拼接组装sql
     * @param parms 执行sql语句中需要的参数集合,string存储表名,value存储map对象集合
     * @return
     */
    public void batchInsert(Map<String, List<Map<String, Object>>> parms, Long startTime) throws Exception {
        try {
            //创建一个线程池,无界队列
            ThreadPoolExecutor executor = new ThreadPoolExecutor(
                    4,
                    4,
                    0L,
                    TimeUnit.SECONDS,
                    new LinkedBlockingQueue<Runnable>(),
                    Executors.defaultThreadFactory());
            // 预先启动所有核心线程
            executor.prestartAllCoreThreads();
            //400一组
            int batchSize = 400;
            // 遍历parms中的所有键值对
            for (Map.Entry<String, List<Map<String, Object>>> entry1 : parms.entrySet()) {
                // 当执行时间超过 90 秒,抛出异常,service层删表
                if (null !=startTime && System.currentTimeMillis() - startTime > 90000) {
                    isRunning = true;
                }
                if (isRunning) {
                    break;
                }
                //驼峰
                List<String> columns = new ArrayList<>();
                //字段
                List<String> columns1 = new ArrayList<>();
                //占位符?
                List<String> values = new ArrayList<>();
                //表名
                String tableName = entry1.getKey();
                //List<Map<String, Object>>
                List<Map<String, Object>> value1 = entry1.getValue();
                // value是List<Map<String, Object>>类型,进行第二次遍历
                List<Map<String, Object>> list =  value1;
                log.info("解析结构化数据,应插入" + tableName + "临时表-" + list.size() + "条!");
                //初始化所需线程数
                int threadCount = (list.size() + batchSize - 1) / batchSize;
                CountDownLatch latch = new CountDownLatch(threadCount);//初始化CountDownLatch
                //结构化数据分为400一组
                List<List<Map<String, Object>>> batchedList = getbatchedList(list, batchSize);
                //获取字段集合和占位符?,拼接sql
                String sql = getSql(columns, columns1, values, tableName, list);
                //批量插入,400一组(多线程),200一插
                for (List<Map<String, Object>> subList : batchedList) {
                    executor.execute(new InsertTask(dataSource, columns, subList, sql, latch, executor));
                }
                latch.await();
            }
            //关闭线程池
            executor.shutdown();
            //检测任务和线程池是否真正关闭
            while (!executor.isTerminated()){
                if (null !=startTime && System.currentTimeMillis() - startTime > 90000) {
                   break;
                }
                Thread.sleep(100);
            }
            if (isRunning) {
                throw new Exception("解析结构化数据,批量插入临时表时异常!");
            }
            log.info("该临时表插入完成----->\n");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("解析结构化数据,批量插入临时表时异常!");
            throw new Exception("batch insert failed",e);
        } finally {
            isRunning = false;
        }
    }




    //获取字段集合和占位符?,拼接sql
    private String getSql(List<String> columns, List<String> columns1, List<String> values, String tableName, List<Map<String, Object>> list) {
        for (Map.Entry<String, Object> entry2 : list.get(0).entrySet()) {
            if (null != entry2.getValue()) {
                //格式转换:驼峰转换为数据库字段(map中存放的格式为驼峰)
                String field = entry2.getKey();
                columns.add(field);
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < field.length(); i++) {
                    char c = field.charAt(i);
                    if (Character.isUpperCase(c)) {
                        sb.append("_");
                    }
                    sb.append(Character.toLowerCase(c));
                }
                field = sb.toString().toUpperCase();
                columns1.add(field);
                values.add("?");
            }
        }
        return "INSERT INTO " + tableName + "(" + String.join(",", columns1) + ") VALUES(" + String.join(",", values) + ")";
    }




 /*
     * IntStream.range(n,m)左闭右开
     * mapToObj(n,m)左闭右开
     * list.subList(n,m)左闭右开 截取指定范围的数据
     * @param list
     * @return java.util.List<java.util.List<java.util.Map<java.lang.String,java.lang.Object>>>
     */
    private List<List<Map<String, Object>>> getbatchedList(List<Map<String, Object>> list, int batchSize) {
        List<List<Map<String, Object>>> batchedList =
                //控制组数,每个整数表示一组 左闭右开
                IntStream.range(0, (list.size() + batchSize - 1) / batchSize)
                        //截取指定范围数据映射到对应的组里,i是第几组,从0开始. Math.min()考虑不足600的情况
                        .mapToObj(i -> list.subList(i * batchSize, Math.min((i + 1) * batchSize, list.size())))
                        .collect(Collectors.toList());
        return batchedList;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值