Java百万数据导出excel

问题:

1、Excel 2007及以上版本(.xlsx),最大支持单Sheet 一百万(1048576)行,如果要在一个Excel文件中写入大于1百万行的数据,则需要每百万行创建一个Sheet。

2、数据一般是从数据库中查出来的,如果一次查出太多数据内存可能装不下出现OOM,需要分页查询*流式查询导出

思路:

一百万条数据,分为100个线程去同时分页查,每一页10000条(也就是每个sheet一万条)。

然后等待所有线程查询完毕后,在main线程中调用easyExcel的api将其写入。

easyExcel示例:

@Test
    void SimpleWriteByThread() throws IOException, InterruptedException {
        /**
         * 多线程插入:开启100个进程去同时分页查,然后放到一个map中,阻塞起来,然后main去遍历这个map,然后遍历
         */
        long current=System.currentTimeMillis();
        String fileName = "user.xlsx";
        OutputStream outputStream = new FileOutputStream(fileName);
        //记录<分页页数,对应数据>的map
        Map<Integer, List<UserTest>> map = new HashMap<>();
        //定义一个线程执行Service,100个固定的线程池。
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        long count = userTestMapper.countByExample(new UserTestExample());
        int pages=100;
        int pageSize= (int) (count/pages);
        //开启一个countDownLatch计数器,等到各线程执行完成后再执行main线程
        CountDownLatch countDownLatch = new CountDownLatch(pages);
        for (int i = 0; i < pages; i++) {
            int currentI=i;
            executorService.submit(() -> {
                //每个线程分页查,并将data put到map中
                PageHelper.startPage(currentI+1,pageSize);
                List<UserTest> userTests = userTestMapper.selectByExample(new UserTestExample());
                map.put(currentI,userTests);
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        //main唤醒,遍历map,将map的key作为sheet数,将value插入各sheet
        try (ExcelWriter excelWriter = EasyExcel.write(outputStream, UserTest.class).build()){
            for (Map.Entry<Integer,List<UserTest>> entry : map.entrySet()){
                Integer pageNum = entry.getKey();
                List<UserTest> pageData = entry.getValue();
                WriteSheet writeSheet = EasyExcel.writerSheet(pageNum, "模板" + pageNum).build();
                excelWriter.write(pageData, writeSheet);
            }
        }
        long end=System.currentTimeMillis();
        System.out.println("耗时:"+(end-current)+"ms");//10w => 2345ms 100w => 8809ms
        outputStream.close();
    }

jvm调优:在windows系统中java安装目录中jdk/bin/目录下的jvisualvm.exe启动程序。双击启动

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值