poi实现多线程大数据导出

多线程导出

2000万数据量导出200万数据,10个字段,耗时16s.

@Configuration
@Slf4j
public class AsyncTaskPoolConfig {
    @Value("${async.executor.thread.core_pool_size}")
    private int corePoolSize;
    @Value("${async.executor.thread.max_pool_size}")
    private int maxPoolSize;
    @Value("${async.executor.thread.queue_capacity}")
    private int queueCapacity;
    @Value("${async.executor.thread.name.prefix}")
    private String namePrefix;

    @Bean(name = "taskExecutor")
    public Executor asyncServiceExecutor() {
        log.warn("start taskExecutor");
        //在这里修改
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(corePoolSize);
        //配置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置队列大小
        executor.setQueueCapacity(queueCapacity);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(namePrefix);
        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }
}

配置

spring:
  # DataSource Config
  datasource:
    druid:
      url: jdbc:mysql://127.0.0.1:3306/maruko?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 123456
      initial-size: 5
      max-active: 10
      min-idle: 10
      max-wait: 20
      #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      time-between-eviction-runs-millis: 60000
# 异步线程配置
# 配置核心线程数
async:
  executor:
    thread:
      core_pool_size: 10
  # 配置最大线程数
      max_pool_size: 20
  # 配置队列大小
      queue_capacity: 30
  # 配置线程池中的线程的名称前缀
      name:
        prefix: async-excl-
 @GetMapping(value = "/exportEasyExcel2")
    public void exportEasyExcel2() {
        long start = System.currentTimeMillis();
        // 数据的总数
        int dataTotalCount = 2000000;
        int limit = 150000;
        // 计算出多少页,即循环次数
        int count = dataTotalCount / limit + (dataTotalCount % limit > 0 ? 1 : 0);
        CountDownLatch countDownLatch = new CountDownLatch(count);
        for (int i = 1; i <= count; i++) {
            Map<String, Object> map = new HashMap<>(3);
            map.put("start", (i - 1) * limit);
            map.put("end", limit);
            map.put("path", "d:\\excel\\");
            iUserService.excuteAsyncTaskDatabase(map, countDownLatch);
        }
        try {
            countDownLatch.await(); //保证之前的所有的线程都执行完成,才会走下面的;
            // 这样就可以在下面拿到所有线程执行完的集合结果
        } catch (Exception e) {
            log.error("阻塞异常:" + e.getMessage());
        } finally {
            long end = System.currentTimeMillis();
            log.info("excel任务执行完毕,共耗时:  " + (end - start) + "ms");
        }
    }
 @Override
    @Async("taskExecutor")
    public void excuteAsyncTaskDatabase(Map<String, Object> map, CountDownLatch cdl) {
        try {
            long startTime = System.currentTimeMillis();

            List<String> title = Arrays.asList("主键ID", "用户名称", "邮箱", "手机号", "性别", "密码", "年龄", "创建时间", "更新时间");

            List<String> key = Arrays.asList("id", "name", "email", "phone", "gender", "password", "age", "create_time", "update_time");

            List<Map<String, Object>> list = baseMapper.queryList(map);
            log.info("线程:" + Thread.currentThread().getName() + "读取数据耗时 :" + (System.currentTimeMillis() - startTime) + "ms,查询到数据量为:" + list.size());
            String filePath = map.get("path").toString() + UUID.randomUUID() + ".xlsx";
            // 调用导出的文件方法
            Workbook workbook = SxssfWorkbookUtil.createWorkbook(title, key, list);
            //将workbook转换为文件
            ExcelUtil.workbookToFile(workbook, filePath);
            long endTime = System.currentTimeMillis();
            log.info("线程:" + Thread.currentThread().getName() + "导出excel" + map.get("start") + ".xlsx成功 ,耗时 :" + (endTime - startTime) + "ms");

            log.info("剩余任务数  ===========================> " + cdl.getCount());
        } catch (Exception e) {
            log.error("文件生成异常" + e.getMessage());
        } finally {
            // 执行完线程数减1
            cdl.countDown();
        }

    }
    /**
     * 大文件导出
     *
     * @param title 列标题头
     * @param key   字段英文
     * @param data  数据
     * @return
     */
    public static SXSSFWorkbook createWorkbook(List<String> title, List<String> key, List<Map<String, Object>> data) {

        try {
            //创建poi导出数据对象
            SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(100);

            //创建sheet页
            SXSSFSheet sheet = sxssfWorkbook.createSheet();
            //设置表头信息
            SXSSFRow headRow = sheet.createRow(0);

            //设置标题头
            for (int j = 0; j < title.size(); j++) {
                headRow.createCell(j).setCellValue(title.get(j));
            }

            //遍历数据
            for (int i = 0; i < data.size(); i++) {
                SXSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1);
                for (int j = 0; j < key.size(); j++) {
                    dataRow.createCell(j).setCellValue(data.get(i).get(key.get(j)).toString());
                }
            }

            return sxssfWorkbook;
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
poi3.9是Apache POI框架的一个版本,可以用于在大数据环境中导出Excel文件。使用poi3.9进行大数据Excel导出有以下几个步骤。 首先,导入poi3.9的相关 jar 包。这些 jar 包包括 poi-3.9.jar、poi-ooxml-3.9.jar、poi-ooxml-schemas-3.9.jar 和 xmlbeans-2.3.0.jar。 然后,创建一个工作簿(Workbook)对象,可以使用 HSSFWorkbook 或者 XSSFWorkbook,分别代表用于处理 .xls 和 .xlsx 格式的工作簿。 接下来,创建一个工作表(Sheet)对象,可以使用 createSheet 方法来创建一个新的工作表。该方法返回一个 Sheet 对象,可以对工作表进行进一步的操作。 然后,在工作表中创建行(Row)对象,可以使用 createRow 方法。该方法返回一个 Row 对象,可以添加单元格(Cell)。 然后,在每一行中创建单元格,可以使用 createCell 方法。该方法根据所需的数据类型(数值、字符串等)创建一个单元格,并将其添加到行中。 接着,将数据填充到单元格中,可以使用 setCellValue 方法。根据数据类型的不同,可以使用 setCellValue 方法设置不同类型的数据,例如 setCellValue(String value)、setCellValue(int value) 等。 最后,使用 FileOutputStream 将工作簿写入到磁盘上的文件中。可以创建一个文件输出流(FileOutputStream)对象,将工作簿写入到指定的文件路径中。 综上所述,使用poi3.9进行大数据Excel导出需要导入相关的jar包,创建工作簿和工作表对象,创建行和单元格对象,并将数据填充到单元格中,最后将工作簿写入到磁盘文件中。这样就可以在大数据环境中成功进行Excel导出了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值