Java:使用静态变量在基于Web的应用程序中存储特定于应用程序的数据

时间:2012-09-24 10:17:12

标签: java

我正在开发一个现有的基于Web的应用程序,它使用静态地图来存储特定于应用程序的数据。

这是我下面的代码,负责将数据存储在ConcurrentHashMap中,如下所示。

public class MyClass 

    // Class variable
    private static Map<String, UserThread> usermap = new ConcurrentHashMap<String, UserThread>();  

// Inside a Method 
public void userData()
 {
 UserThread  userThread= usermap.get(getLoginId());
 if (userThread == null) {
 userThread = new UserThread();
 userThread.start();
 usermap.put(getLoginId(), userThread);
 }
}

应用程序工作正常,我的问题是,这是一个有效的代码,因为我们可以将数据存储在静态变量中吗? (此处静态ConcurrentHashMap包含特定于应用程序的数据)

4 个答案:

答案 0 :(得分:2)

应避免使用任何类型的静态变量和缓存,尤其是在多线程环境(如Web应用程序)中。您的代码存在一些问题:

  1. 您是否从地图中删除了UserThreads?你怎么知道什么时候应该被删除?如果客户端的浏览器崩溃了怎么办?如果您不删除它们,则在应用程序运行一段时间后,您会要求出现内存不足错误。
  2. 以您使用它的方式使用ConcurrentHashMap不是线程安全的,因为另一个线程可能会在if (userThread == null)usermap.put(getLoginId(), userThread);之间添加UserThread。 HashMap的Concurent版本并没有神奇地解决所有线程安全问题。
  3. 在servlet容器中生成自己的线程不是一个好主意。有更好的方法来执行后台任务,但首先你需要说明线程正在尝试做什么。
  4. 在任何类型的应用程序中,通常使用任何类型的静态缓存都是个坏主意。在您的情况下,将特定于应用程序的数据保存在用户的会话中会更好。

答案 1 :(得分:1)

使用静态地图,你会遇到内存泄漏的风险,除非你确定添加到地图中的每个条目的生命周期,即谁将添加它们,条目将保留多长时间以及何时将它们保留被移除,以便在GC期间可以声明它们。否则,您的应用程序将耗尽内存并开始抛出OOME。

答案 2 :(得分:0)

在这种情况下,将在一台计算机上登录的用户将具有与第二台计算机上相同的会话。我敢打赌,这不是一个好方法。

前段时间我曾问过Semi static field in Java application,而Alessandro Santini给了我ThreadLocal非常好的解决方案。看看这个。

答案 3 :(得分:0)

  1. AFAIK根据规范不能在容器内启动自己的线程。您应该使用WorkManager进行此操作。但我所知道的唯一一个实际上是强制执行该规则的服务器是Websphere Application服务器。

  2. 原则上静态变量是可以的,当然如果你在集群环境中运行,每个服务器都有自己的静态变量实例。这可能是也可能不是问题。

  3. 从技术上讲,你可能没问题。

    另一方面,我真的好奇你要用所有这些线程实现的目标。如果你为每个用户启动一个线程,这对于DOS攻击来说是一个很好的攻击媒介。我也不知道你为什么要这样做。