问题:
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
启动程序。双击启动