zoukankan      html  css  js  c++  java
  • 多线程批量上传excel

      多线程处理批量上传excel解析后入库操作

    思路:上传文件文件控制在200以内,每个文件对应一个订单,多线程处理上传的文件,每个线程处理一部分,最后在合并结果,返回前端展示。

    • 难点1:任务划分,根据文件数量算出需要启用的线程数,然后使用栈存放List的下标
    • 难点2:处理业务,每个线程执行完成后收集结果,使用CountDownLatch计数;使用Map,key对应存储线程id,value存储线程的处理结果
    • 难点3:合并结果,合并处理Map的结果,返回结果
          public Result importMultipleExcel2(MultipartHttpServletRequest request){
              
              //开始时间
              long time1 = System.currentTimeMillis();
              
              Iterator<String> fileNames = request.getFileNames();
              Map<Thread, List<Map<String, Object>>> threadData = new HashMap<>();
              Map<Thread, Integer> successData = new HashMap<>();
              Map<Thread, Integer> failData = new HashMap<>();
              try {
                  while (fileNames.hasNext()) {
                      List<MultipartFile> fileList = request.getFiles(fileNames.next());
                      if (fileList.size() > 0) {
                          //文件数量
                          int size = fileList.size();
                          //每个线程处理的文件数量
                          final int number = 30;
                          //开启的线程数
                          int count = size % number == 0 ? (size / number) : (size / number + 1);
                          //初始化线程池
                          ExecutorService executor = Executors.newFixedThreadPool(count);
                          //创建计数器
                          CountDownLatch end = new CountDownLatch(count);
                          //分配要处理的任务
                          Stack <Map<Integer, Integer>> stack = new Stack<>();
                          for(int i=0;i<count;i++){
                              final int from = i * number;
                              final int to = (i + 1) * number > size ? size : (i + 1) * number;
                              
                              Map<Integer, Integer> map = new HashMap<>();
                              map.put(from, to);
                              stack.push(map);
                          }
                           //为每个线程分配要执行的数据
                           for(int i=0;i<count;i++){
                              executor.execute(()->{
                                  try {
                                      Map<Integer, Integer> kvmap = stack.pop();
                                      logger.debug("kvmap:"+kvmap);
                                      kvmap.forEach((key , value)->{
                                          List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
                                          int success = 0;
                                          int fail = 0;
                                          for (int n = key; n < value; n++) {
                                              Result result = 处理导入excel的业务方法;
                                              String orFileName = fileList.get(n).getOriginalFilename();
                                              if (result.get("code").toString().equals("0")) {
                                                  success = success + 1;
                                              } else {
                                                  fail = fail + 1;
                                                  Map<String, Object> params = new HashMap<String, Object>();
                                                  params.put("fileName", orFileName);
                                                  params.put("status", result.get("msg"));
                                                  params.put("code", "1");
                                                  list.add(params);
                                              }
                                          }
                                          threadData.put(Thread.currentThread(), list);
                                          successData.put(Thread.currentThread(), success);
                                          failData.put(Thread.currentThread(), fail);
      
                                  });
                                      
                                  }catch (Exception e) {
                                      e.printStackTrace();
                                  }finally {
                                      end.countDown();  
                                  }
                              });
                           }
                           end.await();
                           //关闭线程池
                           executor.shutdown();
                      }
                  }
              } catch (Exception e) {
                  e.printStackTrace();
                  throw new SysAdminServiceException("导入文件失败");
              }
      
              // 合并处理每个线程的数据
              Integer[] success = {0};
              Integer[] fail = {0};
              List<Map<String, Object>> list = new ArrayList<>();
              successData.forEach((key, value) -> {
                  success[0] = success[0] + value;
              });
              failData.forEach((key, value) -> {
                  fail[0] = fail[0] + value;
              });
              threadData.forEach((key, value) -> {
                  list.addAll(value);
              });
              
              long time2 = System.currentTimeMillis();
              System.out.println("总耗时:"+(time2-time1));
              return Result.ok().put("msgList", list).put("cheng", success[0]).put("importMsg", fail[0]);
          }
  • 相关阅读:
    Insert into select语句把生产服务器炸了!
    人人都能看懂的 6 种限流实现方案
    Idea 快捷生成类注释与方法注释
    拦截器
    java 泛型
    SQL语句总结
    深入浅出Git教程(转载)
    (转载)CSS3与页面布局学习总结(三)——BFC、定位、浮动、7种垂直居中方法
    css中常见margin塌陷问题之解决办法
    css中固定宽高div与不固定宽高div垂直居中的处理办法
  • 原文地址:https://www.cnblogs.com/yangjiming/p/13826887.html
Copyright © 2011-2022 走看看