Apache POI - 缓存工作簿是重用的最佳方式吗?

时间:2015-12-31 23:57:36

标签: java apache-poi

我们已经在生产中使用Apache POI几年并取得了良好的效果。目前在3.11版本上。我们只使用HSSF(根据我们的测试,比XSSF更快,我们可以不使用XLSX。)

我们目前保留了“同步工作簿运行者”的缓存映射,大约70左右的内存。想想每个XLS产品,地图键告诉我们使用哪个产品。我们在启动时加载缓存,所以我们永远不会实时读取文件。

我们的同步跑步者大致如下:

public class PoiProcessorSynchronized {
  private Workbook workbook;
  public synchronized Map<String, Object> process(Request request) {
    engine.process(workbook, request); //request has input/output params
  }
}

这使得性能相当不错(过去24小时平均为112k,平均为112k),有些纸张很慢,有些很快。我们在处理之间手动将输入重置到工作表中,以确保工作表之间的工作表是清洁的。

保持对工作表的同步处理是为了防止错误计算。我们最初看到一些错误的计算而没有控制对纸张的访问。自从我们这样做以来,它一直很稳固。

我担心的一些问题:

  1. 每个XLS每个服务器一次只能处理一个请求。我们可以通过访问某种我认为的处理器池来解决这个问题
  2. 工作簿的内存相对较大。如果我们继续将XLS添加到缓存中,我们必须添加越来越多的内存。
  3. 还有其他人试图做类似的事吗?这种方法现在正在发挥作用,但感觉应该有更好的方法。

    我们可以缓存其他工作簿吗?或序列化什么?

    有没有人通过工作簿成功处理高容量而不同步它们?如果是这样的话?

2 个答案:

答案 0 :(得分:2)

在库级别,Apache POI是线程安全的。在工作簿级别(+ sheet / row / cell / etc级别),Apache POI不是线程安全的。给定的工作簿一次只能由一个线程处理。如果您有多个并行工作的线程,则它们必须具有自己的工作簿才能进行处理。不支持在同一工作簿上工作的两个线程(包括在同一工作簿中处理不同的工作表)。

总的来说,加载.xls文件相当快。使用File rather than an InputStream if you can稍微降低内存并加快加载速度。请参阅memory and performance FAQ for some guides。确保您使用最新版本的Apache POI进行bug fixes and improvements

对于您的特定情况,最流行的工作簿的某种缓存可能会很好。也许只适用于较大的流行工作簿,小型工作簿总是按需加载。

否则,尝试进行一些分析,看看POI是否在某些地方为某些文件做了太多工作。然后report that and work to get it fixed,项目总是欢迎性能提升!

答案 1 :(得分:1)

这个问题的答案完全取决于POI本身是否以完全线程安全的方式实现。

鉴于并发和线程安全未在POI站点上的文档或FAQ中的任何地方解决,您必须假设它不是线程安全的。

快速查看POI 3.5 HSSFWorkbook code at DocJar显示没有同步关键字,并且使用了简单的非同步集合......所以不,它不是线程安全的。

因此,您的同步方法可能是您所能做到的最佳方法。