多线程导入execl

/**
     * 导入
     *
     * @return
     * @author 
     */
    @RequestMapping(value = "/sf/import", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "-导入excel保存", notes = "-导入excel保存", response = String.class)
    public BaseResult<Object> sfImportSave(
            HttpServletRequest request) throws IOException, InterruptedException {
        BaseResult<Object> result = new BaseResult<>();
        SysUserRealmDto currentUser = UserUtils.getCurrentUser();
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (isMultipart) {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            List<MultipartFile> fileList = multipartRequest.getFiles("file");
            HashMap<String, Long> orgMap = organizationService.findNameId();
            if (null != fileList) {
                MultipartFile multipartFile = fileList.get(0);
                ImporterFactory.Result<SfInformation> list = importerFactory.process(multipartFile.getInputStream(), multipartFile.getOriginalFilename(),
                        SfInformation.class, SfInformationConfig.class, orgMap);
                if (CollectionUtils.isNotEmpty(list.getError())) {
                    result.setCode(ResultCodeEnum.HTTP_PARAMS_ERROR.getCode());
                    result.setMsg(list.getErrorByMsg());
                    return result;
                }
                SfScheduleDto proc = new SfScheduleDto();
                int size = list.getList().size() / 5;//切分粒度,每size条数据,切分一块,交由一条线程处理
                int countNum = 0;//当前处理到的位置
                List<SfInformation> listRes = list.getList();
                int count = listRes.size() / size;//切分块数
                int threadNum = 0;//使用线程数
                if (count * size != listRes.size()) {
                    count++;
                }
                final CountDownLatch countDownLatch = new CountDownLatch(count);
                //使用Guava的ListeningExecutorService装饰线程池
                ExecutorService executorService = Executors.newFixedThreadPool(count);
                List<Future<Map>> futures = new ArrayList<>();
                while (countNum < count * size) {
                    //切割不同的数据块,分段处理
                    threadNum++;
                    countNum += size;
                    MyCallable myCallable = new MyCallable();
                    myCallable.setOrgId(currentUser.getOrgId());
                    myCallable.setList(ImmutableList.copyOf(
                            listRes.subList(countNum - size, listRes.size() > countNum ? countNum : listRes.size())));
                    myCallable.setCountDownLatch(countDownLatch);
                    futures.add(executorService.submit(myCallable));

                }

                  /*  //回调函数
                    Futures.addCallback(listenableFuture, new FutureCallback<Map>() {
                        //任务处理成功时执行
                        @Override
                        public void onSuccess(Map map) {
                            long count1 = countDownLatch.getCount();
                            System.out.println("第" + count1 + "次处理完成");
                            countDownLatch.countDown();
                            countx=countx+  (Integer) map.get("x");
                            map.get("y");

                        }

                        //任务处理失败时执行
                        @Override
                        public void onFailure(Throwable throwable) {
                            countDownLatch.countDown();
                            System.out.println("处理失败:" + throwable);
                        }
                    }, executorService);*/


                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    executorService.shutdown();
                }
                Integer sumx = 0;
                Integer sumy = 0;
                for (Future<Map> future : futures) {
                    try {
                        sumx += (Integer) future.get().get("x");
                        sumy += (Integer) future.get().get("y");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
                proc.setCount(listRes.size());// 总条数
//                    proc.setProc(sumx + sumy);// 进度 = 导入成功 + 子单号重复
                proc.setSuccessCount(sumy);// 导入成功
                proc.setDumpCount(sumx);// 子单号重复
                //  redisTemplate.opsForValue().set(KEY_PREFIX + timestamp, proc, DEFAULT_EXPIRATION_TIMES, TimeUnit.SECONDS);

                result.setData(proc);
                System.out.println("------------结果处理完毕,返回完毕,使用线程数量:" + threadNum);
                result.setMsg(list.getSuccess());
            }
        }
        return result;
    }


    class MyCallable implements Callable {
        private List<SfInformation> list;
        private Long orgId;
        private CountDownLatch countDownLatch;

        @Override
        public Object call() throws Exception {
            Map map = new HashMap();
            int x = 0;
            int y = 0;

            System.out.println("当前线程名称" + Thread.currentThread());
            //模拟对数据处理,然后返回
            for (int i = 0; i < list.size(); i++) {
                DistributionSet dis = distributionSetService.findCode(list.get(i).getNetCode());
                if (dis != null) {
                    list.get(i).setOrgId(dis.getOrgId());
                }
                SfInformation sf = sfInformationService.findOrderNo(list.get(i).getOrderNo());
                if (sf != null) {
                    x++;
                } else {
                    list.get(i).setGuideTime(System.currentTimeMillis());
                    list.get(i).setGuideOrgId(orgId);
                    sfInformationService.create(list.get(i));
                    y++;
                }
            }
            countDownLatch.countDown();
            map.put("x", x);
            map.put("y", y);
            return map;
        }

        public void setList(List<SfInformation> list) {
            this.list = list;
        }

        public void setOrgId(Long orgId) {
            this.orgId = orgId;
        }

        public void setCountDownLatch(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }
    }

Java实现多线程导入Excel通常需要将Excel文件分割成多个部分,然后将每个部分分配给一个线程进行处理,最后将结果合并。下面是一个简单的实现示例: ```java public class ExcelImporter { private static final int NUM_THREADS = 4; // 线程数 public void importExcel(String filePath) throws Exception { File file = new File(filePath); FileInputStream inputStream = new FileInputStream(file); Workbook workbook = new XSSFWorkbook(inputStream); // 使用POI解析Excel Sheet sheet = workbook.getSheetAt(0); // 获取第一个Sheet int rows = sheet.getPhysicalNumberOfRows(); // 获取总行数 int rowPerThread = rows / NUM_THREADS; // 每个线程处理的行数 ExecutorService executorService = Executors.newFixedThreadPool(NUM_THREADS); List<Future<List<Data>>> futures = new ArrayList<>(); for (int i = 0; i < NUM_THREADS; i++) { int startRow = i * rowPerThread; int endRow = i == NUM_THREADS - 1 ? rows : (i + 1) * rowPerThread; Callable<List<Data>> task = new ExcelImporterTask(sheet, startRow, endRow); Future<List<Data>> future = executorService.submit(task); futures.add(future); } List<Data> dataList = new ArrayList<>(); for (Future<List<Data>> future : futures) { List<Data> data = future.get(); dataList.addAll(data); } executorService.shutdown(); // 将结果合并 // ... } } class ExcelImporterTask implements Callable<List<Data>> { private Sheet sheet; private int startRow; private int endRow; public ExcelImporterTask(Sheet sheet, int startRow, int endRow) { this.sheet = sheet; this.startRow = startRow; this.endRow = endRow; } @Override public List<Data> call() throws Exception { List<Data> dataList = new ArrayList<>(); for (int i = startRow; i < endRow; i++) { Row row = sheet.getRow(i); Data data = new Data(); data.setXXX(row.getCell(0).getStringCellValue()); data.setYYY(row.getCell(1).getStringCellValue()); dataList.add(data); } return dataList; } } class Data { private String xxx; private String yyy; // getter/setter // ... } ``` 上面的代码将Excel文件分割成4个部分,每个部分由一个线程处理,最后将结果合并。需要注意的是,这个示例只处理了一个Sheet,并且没有考虑到线程安全的问题。在实际应用中,需要根据具体情况进行修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值