编辑:我发现单例的构造函数被多次调用,所以看起来这些类被单独的类加载器加载了不止一次。如何在 Tomcat 中创建全局单例?我一直在谷歌搜索,但到目前为止没有运气。
我有一个像这样构造的单例对象:
private static volatile KeyMapper mapper = null;
public static KeyMapper getMapper()
{
if(mapper == null)
{
synchronized(Utils.class)
{
if(mapper == null)
{
mapper = new LocalMemoryMapper();
}
}
}
return mapper;
}
KeyMapper 类基本上是 HashMap 的同步包装器,只有两个功能,一个添加映射,一个删除映射。在我的 32 位 Windows 机器上运行 Tomcat 6.24 时一切正常。但是,当在 64 位 Linux 机器(带有 OpenJDK 1.6.0-b09 的 CentOS 5.4)上运行时,我添加了一个映射并打印出 KeyMapper 使用的 HashMap 的大小以验证是否添加了映射(即验证大小 = 1)。然后我尝试用另一个请求检索映射,但我一直得到 null,当我检查 HashMap 的大小时它是 0。我相信映射不会被意外删除,因为我已经注释掉了所有删除调用(而且我不使用 clear 或任何其他修改器,只是获取和放置)。
请求通过 Tomcat 6.24(配置为使用 200 个线程,最少 4 个线程)并且我将 -Xnoclassgc 传递给 jvm 以确保该类不会无意中被垃圾收集(jvm 也在 -server 中运行模式)。我还向 KeyMapper 添加了一个 finalize 方法,以在它被垃圾收集时打印到 stderr,以验证它没有被垃圾收集。
我无计可施,我想不通为什么前一分钟 HashMap 中的条目在那里,而下一分钟却不在 :(
最佳答案
另一个疯狂的猜测:这两个请求是否可能由您的 Web 应用程序的不同副本提供服务?每个都在自己的 ClassLoader
中,因此具有不同的单例副本。
关于linux - 在多线程 Tomcat 服务器中访问全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2757043/