EasyExcel导出多线程
时间: 2025-03-26 20:02:08 浏览: 47
### 使用 EasyExcel 实现多线程导出 Excel 文件
为了提高大数据量场景下的性能,可以采用多线程分页的方式进行数据处理并导出到 Excel 文件。下面介绍一种最佳实践方法来实现这一目标。
#### 创建自定义的数据读取器类 `DemoDataReader`
该类负责按需加载指定范围内的记录集合,从而减少内存占用:
```java
public class DemoDataReader implements DataReader<DemoData> {
private final List<DemoData> dataList;
public DemoDataReader(List<DemoData> dataList) {
this.dataList = dataList;
}
@Override
public boolean hasNext() throws Exception {
return false;
}
@Override
public DemoData next() throws Exception {
return null;
}
}
```
注意上述模板中的两个抽象方法需要依据实际业务逻辑去具体实现[^1]。
#### 定义用于写入的工作簿监听器 `DemoDataListener`
此组件接收来自不同子任务的结果集,并将其追加至最终的目标文件内:
```java
public class DemoDataListener extends AnalysisEventListener<DemoData> {
/**
* 这里会一行一行的返回头
*/
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {}
/**
* 通过AnalysisContext 可以获取批量数据,建议设置一个批大小(比如:2000)
*
* @param data 单条解析后的对象
* @param context 上下文信息
*/
@Override
public void invoke(DemoData data, AnalysisContext context) {}
/**
* 所有数据解析完成了 都会在 doAfterAllAnalysed 发生调用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {}
}
```
同样地,`invoke()` 和其他回调函数应按照项目需求定制化开发。
#### 编写核心控制流程 `ExcelExport`
此类封装了整个操作过程的核心逻辑,包括初始化资源、分配工作单元给各个执行者以及汇总各部分成果等环节:
```java
public class ExcelExport<T> {
private final ExecutorService threadPool;
private final int pageSize;
private final DataReader<T> reader;
private final DataWriter<T> writer;
public ExcelExport(DataReader<T> reader, DataWriter<T> writer){
this.reader = reader;
this.writer = writer;
this.pageSize = 10_000; // 默认每页大小设为一万条目
this.threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
}
public void export(int startPage, long totalRecordsCount)throws InterruptedException{
CountDownLatch latch = new CountDownLatch((int)Math.ceil(totalRecordsCount / (double)this.pageSize));
IntStream.rangeClosed(startPage, (int)(totalRecordsCount/this.pageSize)+startPage).forEach(pageNo -> {
Runnable task = () -> {
try {
List<T> pageItems = reader.readByPage(pageSize*(pageNo-startPage),pageSize);
writer.writeBatch(pageItems,new DemoDataListener());
} catch (Exception e) {
throw new RuntimeException(e.getMessage(),e.getCause());
} finally {
latch.countDown();
}
};
threadPool.submit(task);
});
latch.await();
threadPool.shutdown();
}
}
```
这段程序展示了如何利用 Java 的并发工具库创建固定数量的工作线程池,并行处理多个页面的数据提取与保存动作;同时运用闭锁机制确保主线程等待所有异步作业完成后才继续向前推进。
最后,在应用程序入口处实例化这些组件并将它们串联起来即可启动完整的导出进程。
阅读全文
相关推荐

















