我正在开发一个现有的基于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
包含特定于应用程序的数据)
答案 0 :(得分:2)
应避免使用任何类型的静态变量和缓存,尤其是在多线程环境(如Web应用程序)中。您的代码存在一些问题:
if (userThread == null)
和usermap.put(getLoginId(), userThread);
之间添加UserThread。 HashMap的Concurent版本并没有神奇地解决所有线程安全问题。 在任何类型的应用程序中,通常使用任何类型的静态缓存都是个坏主意。在您的情况下,将特定于应用程序的数据保存在用户的会话中会更好。
答案 1 :(得分:1)
使用静态地图,你会遇到内存泄漏的风险,除非你确定添加到地图中的每个条目的生命周期,即谁将添加它们,条目将保留多长时间以及何时将它们保留被移除,以便在GC期间可以声明它们。否则,您的应用程序将耗尽内存并开始抛出OOME。
答案 2 :(得分:0)
在这种情况下,将在一台计算机上登录的用户将具有与第二台计算机上相同的会话。我敢打赌,这不是一个好方法。
前段时间我曾问过Semi static field in Java application
,而Alessandro Santini给了我ThreadLocal
非常好的解决方案。看看这个。
答案 3 :(得分:0)
AFAIK根据规范不能在容器内启动自己的线程。您应该使用WorkManager进行此操作。但我所知道的唯一一个实际上是强制执行该规则的服务器是Websphere Application服务器。
原则上静态变量是可以的,当然如果你在集群环境中运行,每个服务器都有自己的静态变量实例。这可能是也可能不是问题。
从技术上讲,你可能没问题。
另一方面,我真的好奇你要用所有这些线程实现的目标。如果你为每个用户启动一个线程,这对于DOS攻击来说是一个很好的攻击媒介。我也不知道你为什么要这样做。