[当我通过servlet访问单例Java对象时,该对象对于给定servlet线程仅是“单个”或“一个实例”,还是在服务器OS(如Linux)上的整个JVM中是单个?
我的意思是,当客户机连接到servlet /服务时,单例对象对于为每个客户机创建的每个线程是唯一的还是在机器中安装的整个JVM中是唯一的?
我认为对象对于每个用户都是唯一的,而不是整个JVM唯一。唯一的持久性信息是您在用户会话中输入的信息。
我不确定,但是我认为您可以使用ClassLoader class来在整个Application Server中拥有一个Class实例,但是我不知道它是如何完成的。
UPDATE:
摘自Java文章"When is a Singleton not a Singleton?"
由不同类加载器同时加载的多个单例当两个类加载器加载一个类时,您实际上有该类的两个副本,每个副本可以具有自己的Singleton实例。这在某些servlet引擎(例如iPlanet)中运行的servlet中尤为重要,其中每个servlet默认情况下都使用自己的类加载器。实际上,访问联合Singleton的两个不同的servlet将获得两个不同的对象。
多类加载器比您想象的更常见。当浏览器从网络上加载供小应用程序使用的类时,它们为每个服务器地址使用一个单独的类加载器。类似地,Jini和RMI系统可以为它们从中下载类文件的不同代码库使用单独的类加载器。如果您自己的系统使用自定义类加载器,则可能会出现所有相同的问题。
如果由不同的类加载器加载,则具有相同名称,甚至具有相同程序包名称的两个类将被视为不同的-即使实际上它们是同一类的字节对字节。不同的类加载器代表区分类的不同名称空间(即使这些类的名称相同),因此两个MySingleton类实际上是不同的。 (请参阅参考资料中的“作为名称空间机制的类装入器”。)由于两个Singleton对象属于同一个名称的两个类,因此乍一看就会出现两个相同类的Singleton对象。
我会说这取决于单例的实现方式,但是对给定应用程序的所有请求都在同一VM中执行,因此对于所有请求,它应该是一个实例。
编辑:这是假定类似于以下简单明了的Singleton实现:
public class MySingleton {
private static MySingleton _instance;
// for sake of simplicity, I've left out handling of
// synchronization/multi-threading issues...
public static MySingleton getInstance() {
if (_instance == null) _instance = new MySingleton();
return _instance;
}
}
是,是Singleton
。但是单例的范围取决于类的位置。
如果位于应用程序内部,则为该应用程序的单例。如果另一个应用程序中存在相同的类,则将为该应用程序创建另一个对象,并且该对象是该应用程序的单例。
如果位于应用程序外部和服务器内部,则对于VM是单例。
创建单例实例时,所有请求实例将为其使用的当前类加载器共享相同的实例。
由于所有Servlets
都在运行在单个JVM
上的Web服务器上运行,因此所有servlet都只有一个Singelton
对象。
据此
https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html
每个Web应用程序都有其自己的类加载器,因此单例对于一个应用程序来说是唯一的,而对另一个应用程序则不可见