我想在多线程环境中写入HSSFWorkBook或XSSFWorkBook。每个线程将在相同或不同的表中进行修改。
try {
String filePath="C:/Test.xlsx";
FileInputStream fileInputStream = new FileInputStream(filePath);
Workbook workbook = new XSSFWorkbook(fileInputStream);
FileOutputStream fos = new FileOutputStream(filePath);
workbook.write(fos);
fos.close();
fileInputStream.close();
} catch(Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
在SOAPUI中的LoadTest with MultiThreading中测试此代码时。我得到了一个例外:
Workbook workbook = new XSSFWorkbook(fileInputStream);
例外情况如下:
org.apache.poi.POIXMLException: org.apache.poi.openxml4j.exceptions.InvalidFormatException: Package should contain a content type part [M1.13]
如果你天真地尝试这样做,你会遇到晦涩难懂的错误和损坏的文档。
它所做的唯一保证是,不同线程中的单独工作簿将正常工作,即任何地方都不存在线程不安全的全局状态。
唯一可行的方法是通过同步块同步对工作簿的每次访问:
synchronized (workbook) {
... access the sheet and the contents
}
只读访问可能有效,但ApachePOI并不能保证对同一工作簿的并发读取访问有效。
更新:现在有一个相应的FAQ条目也说明了这一点。
通过读取文件C:/Test.xlsx
创建XSSFWorkbook
;被调用的构造函数是构造OPCPackage
的XSSFWorkbook(InputStream)
。此C:/Test.xlsx
文件必须有效,即未损坏,不为空。
如果要创建新工作簿,则不应读取空文件,而应使用适当的构造函数。
关于多线程,我还没有测试过,但不同线程可以做什么是有限制的(例如,每个XSSheet
一个)。看看这个邮件档案。
有解决方案。。。我在数组中创建行。。。我在线程中使用数组,Tu-debes-evitar使用在线程中创建行,因为这种方法是由线程安全的监控的
对不起,我不会说英语。。。我太努力了。
static int count=0;
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Products");
sheet.createFreezePane(0, 1); // this will freeze first five rows
int rowCount = 0;
rowCount = getExcelTittle(sucsCompetencia,sucsProveedor, sucsPuntoVenta, sheet, rowCount);
// trucazo para multithread
List<Row> r = new ArrayList<Row>();
//List<Drawing> h = new ArrayList<Drawing>();
//cell creation
for ( int j = 0 ; j < ps.size() + 500 ; j++) {
r.add(sheet.createRow(j));
//h.add(sheet.createDrawingPatriarch());
}
// cells creation .. its a good idea do it
Map<String,Cell> cellMap = new HashMap<String,Cell>();
for (int j = 0 ; j < r.size() ; j++) {
for ( int i = 0 ; i < 9 + sucsCompetencia.size() + sucsProveedor.size() + sucsPuntoVenta.size() ; i++) {
cellMap.put( j + "-" + i, r.get(j).createCell(i));
}
}
Stream<Producto> arrStream = ps.parallelStream();
arrStream.forEach(p->
{
count++;
int contadorPropio = count;
if (contadorPropio % 1000 == 0) log.info("* Procesando Generacion Excel " + contadorPropio + " de " + ps.size());
// if (rowCount == 1000 ) break;
int columnCount = 0;
{
//IMPORTANTEEEEEEEE
Cell cell = cellMap.get(contadorPropio + "-" + columnCount++);
cell.setCellValue(p.getIdProducto());
}
在主线程内创建工作簿,工作簿创建工作表,并将工作表分发给工作线程。主线程应该等待,直到所有工作线程完成。主线程工作簿将数据刷新到流中。然后流式传输到文件中。
如果你想要带示例的源代码,请给我发邮件。我会分享ramesh.niwas@gmail.com