gpt4 book ai didi

java - 如何使用 Tomcat 高效地初始化大型静态数据表

转载 作者:行者123 更新时间:2023-11-28 22:40:38 25 4
gpt4 key购买 nike

我刚开始使用 Java/Tomcat,但我正在努力解决一个用 C++ 很容易解决的问题。

我的网络服务(单一网络应用程序)通过使用输入值在大型预计算表中查找数字答案来工作。我正在为这张表的初始化而苦苦挣扎。

问题详情:

  • 数据表很大(3000x3000);
  • 数据是预先计算的,这种计算非常昂贵(它需要几个小时);
  • 数据是静态的,经过一段时间计算后永远不会改变给定实例;

在 C++ 中,我会定义一个静态常量数组并内联初始化它。我无法在 Java 中执行此操作,显然 Java 中没有静态数据初始化的概念,它需要生成初始化代码并且该代码不能大于 64k。事实上,我什至无法在 Eclipse 中使用静态初始化加载文件,它会挂起。

所以我需要从磁盘上的静态文件初始化表。我尝试将 .csv 文件放在 WEB-INF/static 上,但发现无法从我的 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 进程共享一个实例?

最佳答案

这是我的两分钱:

  1. 关于内存共享,如果您的所有 servlet 都在同一个 WAR (webapp) 中,那么它们将共享静态变量(因为它是同一个类加载器),但是使用专用于此目的的 ServletContext 会更好,请参阅 ServletContext
  2. 如 ServletContext 示例(上面的链接)所示,您不一定需要静态初始化器 - 您可以使用 ServletContextListener 在应用程序启动时初始化(顺便说一句,您也可以按需进行初始化,在“getter ' 的海量数据)。

  3. 如果您想在 2 个不同的 WAR 之间共享内存,我不知道有什么直接的解决方案。理论上,如果带有静态 var 的类位于 TOMCAT_HOME/lib 中,则可以共享它,但恕我直言,这令人困惑和奇怪

  4. 将计算放在文件/存储中是个好主意,因为您可能会发现自己需要重新启动 Tomcat!
  5. 关于如何找到文件,我同意 dmitrievanthony 关于 getResourceAsStream 的评论。基本上,它允许您从类路径(用于定位代码的同一个路径)中获取文件,一个简单的示例是将其放入/WEB-INF/classes/data.csv 中,请参见示例代码 Here (我个人喜欢将这种方法包装在 Spring 框架的“资源”中,但这可能有点矫枉过正)。
  6. 请注意:正如我在上面的评论中提到的,我试图为您针对您选择的设计提出的直接问题提供答案,但如果我处在您的位置,我会停止考虑这种设计(例如,是否易于在服务器之间分发?它是模块化的和可单元测试的吗?“data.csv”是否可以替换为数据库或 MongoDB,甚至是单独的“dataService”WAR?)。但是,如果您已经考虑过,请忽略此评论...

已编辑:ServletContext 示例,没有静态字段:

// Class to encapsulate date:
public class G{
private double[][] data;
public static G loadData(){
data=...// complex loading
}
}
// Usage in ServletContextListener:
public class MyListener implements ServletContextListener{
public void contextInitialized(ServletContext ctx) {
G g= G.loadData();
ctx.put("myData", g);
}
// Usage is Servlet:
doGet(...){
G g=(G) getServletContext().getAttribute("myData");
}

单例模式替代方案(但我建议在可测试性和模块化方面要小心,您可能还想看看 SpringMVC 等框架,但让我们从简单的开始):

// Singleton:
public class G{
private volatile double[][] data;
private G instance;
public static G getInstance(){
// I don't synchronize because I rely on ServletContextListener to initialize once
if(data==null)
data=... // complex loading
return data;
}
}
// ServletContextListener:
public void contextInitialized(ServletContext ctx) {
G.getInstance();
}
// Usage in servlet:
doGet(){
G g=G.getInstance(); // I don't like it in terms of OOD, but it works
}

关于java - 如何使用 Tomcat 高效地初始化大型静态数据表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40492149/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com