【发布时间】:2017-03-22 09:19:28
【问题描述】:
我从 Java/Tomcat 开始,我正在努力解决一个用 C++ 很容易解决的问题。
我的网络服务(单一网络应用程序)通过使用输入值在预先计算的大型表格中查找数字答案来工作。我正在为这个表的初始化而苦苦挣扎。
问题详情:
- 数据表很大(3000x3000);
- 数据是预先计算的,这种计算成本很高(它 需要几个小时);
- 数据是静态的,经过计算后永远不会改变 给定实例;
在 C++ 中,我只需定义一个静态 const 数组并内联初始化它。我在Java中无法做到这一点,显然Java中没有静态数据初始化的概念,它需要生成初始化代码并且该代码不能大于64k。事实上,我什至无法在 Eclipse 中加载带有静态初始化的文件,它会挂掉。
所以我需要从磁盘上的静态文件初始化表。我试图在 WEB-INF/static 上放置一个 .csv 文件,但发现无法从我的 Java 代码中可靠地打开它(例如,绝对路径将位于我的开发和生产环境的不同位置)。
这是我当前的类定义(带有用于初始化的模拟数据):
package com.hmt.restjersey;
public final class G {
static public final float[][] data = new float[3000][3000];
//TODO: actual initialization from file
static {
Logger.writeEventLog("Initializing G table...");
for (int alpha = 0; alpha < 3000; alpha++) {
for (int beta = 0; beta < 3000; beta++) {
data[alpha][beta] = 1.0f / (1 + alpha + beta);
}
}
Logger.writeEventLog("G table initialized.");
}
}
所以,我的问题:
- 如何可靠地访问数据文件(WEB-INF/static/data.csv)来初始化表?
- .csv 文件是有效加载数字数据的最佳方式吗?
另外,由于表很大,我希望在服务器中有一个它的实例以节省内存并加快初始化速度。如何确保所有 servlet 进程共享一个实例?
【问题讨论】:
-
您将拥有多少个 Web 应用程序(WAR)来访问如此庞大的数据?如果您所有的 servlet 都在同一个 webapp 中,它们可以通过静态变量(b/c 它是同一个类加载器)或通过应用程序级别的 ServletContext 轻松共享数据(作为旁注,我建议您注意这一点,尤其是当涉及 OOD 和分发问题时,这是另一个问题)
-
您可能可以将数据文件添加到类路径中,然后通过
this.getClass().getClassLoader().getResourceAsStream("data.csv")加载数据。关于高效加载数值数据的最佳方式,您也可以使用csv或使用protobuf或其他序列化工具序列化的准备好的数据。 -
Java中肯定有静态数据。
-
我的意思是静态数据初始化,而不是“静态”关键字。在 C 中,如果您声明一个变量,如:“const static data[]={1 ,2, 3}”,则数据将直接从二进制文件中访问。在 Java 中,数组将在运行时创建和初始化。
-
并不是那么大:3,000 * 3,000 * 4 = 36,000,000 = 36 megs 来保存 32 位(4 个八位字节)
float原语。