如何用easyExcel的实现导出以及实现多线程分页数据导出

您所在的位置:网站首页 excel中的pdf如何导出 如何用easyExcel的实现导出以及实现多线程分页数据导出

如何用easyExcel的实现导出以及实现多线程分页数据导出

2023-06-17 21:34| 来源: 网络整理| 查看: 265

1.先看一下普通写法     

public class ExcelExport { public static void main(String[] args) { // 输出文件路径 String filePath = "D:/demo.xlsx"; // Sheet名称 String sheetName = "Sheet1"; // 写入数据的Sheet编号 int writeSheet = 0; // 写入数据的Table编号 int writeTable = 0; // 创建ExcelWriter对象 ExcelWriter excelWriter = EasyExcel.write(filePath, DemoData.class).sheet(sheetName).build(); // 准备数据源 List data = new ArrayList(); for (int i = 0; i < 1000000; i++) { DemoData demoData = new DemoData(); demoData.setId(i); demoData.setName("name" + i); data.add(demoData); } // 将数据写入Excel文件中 excelWriter.write0(data, writeSheet, writeTable); // 关闭ExcelWriter对象,释放资源 excelWriter.finish(); } }

需要注意的是,在进行大数据量导出时,为了避免内存溢出,可以考虑使用分页查询或按批次查询的方式读取数据,并在写入Excel文件时采用流式写入或多线程写入的方式,这样可以提高导出效率,并避免内存溢出的问题

2.避免内存溢出的问题我们采取分页

public class ExcelStreamWrite { public static void main(String[] args) { // 输出文件路径 String filePath = "D:/demo.xlsx"; // Sheet名称 String sheetName = "Sheet1"; // 写入数据的Sheet编号 int writeSheet = 0; // 创建ExcelWriter对象 ExcelWriter excelWriter = EasyExcel.write(filePath, DemoData.class).sheet(sheetName).build(); // 准备数据源 List data = new ArrayList(); for (int i = 0; i < 1000000; i++) { DemoData demoData = new DemoData(); demoData.setId(i); demoData.setName("name" + i); data.add(demoData); } // 定义每次写入的数据量 int batchSize = 1000; // 定义写入的起始位置 int start = 0; // 定义写入的结束位置 int end = 0; // 循环写入数据 while (end < data.size()) { // 计算下一次写入的结束位置 end = Math.min(start + batchSize, data.size()); // 获取本次写入的数据 List subList = data.subList(start, end); // 写入数据 excelWriter.write(subList, EasyExcel.writerSheet(writeSheet).build()); // 更新起始位置 start = end; } // 关闭ExcelWriter对象,释放资源 excelWriter.finish(); } }

3.为了提高效率我们多线程导出

定义一个数据读取器,用于从数据源中读取指定页码的数据。 public interface DataReader { /** * 读取指定页码的数据 * * @param pageNum 页码,从1开始 * @param pageSize 每页数据量 * @return 当前页的数据 */ List readData(int pageNum, int pageSize); } 定义一个数据写入器,用于将指定页码的数据写入Excel中。 public interface DataWriter { /** * 写入指定页码的数据 * * @param pageNum 页码,从1开始 * @param data 数据 */ void writeData(int pageNum, List data); } 定义一个导出器,用于启动多线程进行数据导出。

public class ExcelExport { private final DataReader reader; private final DataWriter writer; public ExcelExport(DataReader reader, DataWriter writer) { this.reader = reader; this.writer = writer; } public void export(int threadNum, int pageSize) { ExecutorService executorService = Executors.newFixedThreadPool(threadNum); CountDownLatch countDownLatch = new CountDownLatch(threadNum); for (int i = 0; i < threadNum; i++) { final int threadIndex = i; executorService.execute(() -> { int pageNum = threadIndex + 1; List data = reader.readData(pageNum, pageSize); while (data != null && !data.isEmpty()) { writer.writeData(pageNum, data); pageNum += threadNum; data = reader.readData(pageNum, pageSize); } countDownLatch.countDown(); }); } try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } finally { executorService.shutdown(); } } }

在上面的代码中,我们启动了一个固定线程数的线程池,并使用CountDownLatch实现线程同步。对于每个线程,我们从指定的数据读取器中读取指定页码的数据,然后写入到指定的数据写入器中,直到读取到的数据为空或空集合为止。需要注意的是,每个线程的页码应该从不同的起始位置开始,以保证每个线程读取的数据不重复,也不遗漏。

使用示例代码如下:

public class ExcelExportDemo { public static void main(String[] args) { // 数据读取器 DataReader reader = new DemoDataReader(); // 数据写入器 DataWriter writer = new DemoDataWriter(); // 导出器 ExcelExport export = new ExcelExport(reader, writer); // 启动多线程分页导出 export.export(4, 10000); } }

 测试用例代码

public class ExcelExportDemo { public static void main(String[] args) { // 输出文件路径 String filePath = "D:/demo.xlsx"; // Sheet名称 String sheetName = "Sheet1"; // 写入数据的Sheet编号 int writeSheet = 0; // 创建ExcelWriter对象 ExcelWriter excelWriter = EasyExcel.write(filePath, DemoData.class).sheet(sheetName).build(); // 定义每页数据量 int pageSize = 10000; // 定义数据总量 int totalCount = 100000; // 定义分页查询器 PageQuery pageQuery = new PageQuery(pageNum -> { // 模拟从数据库中查询指定页码的数据 List data = new ArrayList(); int startIndex = (pageNum - 1) * pageSize; int endIndex = Math.min(startIndex + pageSize, totalCount); for (int i = startIndex; i < endIndex; i++) { DemoData demoData = new DemoData(); demoData.setId(i); demoData.setName("name" + i); data.add(demoData); } return data; }); // 定义数据写入器 DataWriter dataWriter = new ExcelDataWriter(excelWriter, writeSheet); // 定义导出器 ExcelExport export = new ExcelExport(pageQuery, dataWriter); // 启动多线程分页导出 export.export(4); // 关闭ExcelWriter对象,释放资源 excelWriter.finish(); } } public class ExcelDataWriter implements DataWriter { private final ExcelWriter excelWriter; private final int writeSheet; public ExcelDataWriter(ExcelWriter excelWriter, int writeSheet) { this.excelWriter = excelWriter; this.writeSheet = writeSheet; } @Override public void writeData(int pageNum, List data) { WriteSheet writeSheet = EasyExcel.writerSheet(this.writeSheet).build(); excelWriter.write(data, writeSheet); } }

在上面的示例代码中,我们使用了一个PageQuery和一个ExcelDataWriter分别实现了DataReader和DataWriter接口,用于分页查询和写入数据。每个线程读取10000条数据,共启动4个线程进行数据导出。使用EasyExcel进行流式写入,避免一次性将全部数据加载到内存中,从而避免内存溢出的问题。在测试环境下,可以在几秒钟内导出100000条数据。实际的导出效率取决于具体的硬件环境和数据源的复杂度。



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3