0

当我从一个 servlet 访问一个单例 Java 对象时,该对象只是给定 servlet 线程的“单个”或“一个实例”,还是整个服务器操作系统(如 Linux)上的 JVM 中的单个?

我的意思是当客户端连接到 servlet/服务时,单例对象对于为每个客户端创建的每个线程是唯一的,还是在机器中安装的整个 JVM 中是唯一的?

4

6 回答 6

4

我认为该对象对于每个用户都是唯一的,而不是整个 JVM。唯一持久的信息是您放入用户会话的信息。

我不确定,但我认为您可以使用ClassLoader 类在整个应用程序服务器中拥有一个类的实例,但是我不知道它是如何完成的。

更新:

摘自 Java 文章“什么时候单例不是单例?”

不同的类加载器同时加载多个单例 当两个类加载器加载一个类时,你实际上有两个类的副本,每个副本都可以有自己的单例实例。这与在某些 servlet 引擎(例如 iPlanet)中运行的 servlet 尤其相关,其中每个 servlet 默认使用自己的类加载器。事实上,访问联合 Singleton 的两个不同的 servlet 将获得两个不同的对象。

多个类加载器比您想象的更常见。当浏览器从网络加载类以供小程序使用时,它们为每个服务器地址使用单独的类加载器。类似地,Jini 和 RMI 系统可以为它们下载类文件的不同代码库使用单独的类加载器。如果您自己的系统使用自定义类加载器,则可能会出现所有相同的问题。

如果由不同的类加载器加载,两个同名的类,甚至同一个包名,都被视为不同的——即使它们实际上是逐字节的同一个类。不同的类加载器代表区分类的不同命名空间(即使类的名称相同),因此这两个 MySingleton 类实际上是不同的。(请参阅参考资料中的“类加载器作为命名空间机制”。)由于两个 Singleton 对象属于两个同名的类,因此乍一看会出现同一个类的两个 Singleton 对象。

于 2012-07-06T09:02:16.817 回答
3

我想说这取决于单例的实现方式,但是给定应用程序的所有请求都在同一个 VM 中执行,因此它应该是所有请求的一个实例。

编辑:这是假设一个简单的单例实现类似于:

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;
    }
}
于 2012-07-06T08:56:33.320 回答
1

是的Singleton。但是单例的范围取决于类所在的位置。

如果它位于应用程序内部,则该应用程序是单例的。如果相同的类存在于另一个应用程序中,则为该应用程序创建另一个对象,并且该应用程序是单例的。

如果它位于应用程序外部和服务器内部,则它对于 VM 来说是单例的。

于 2012-07-06T09:08:47.867 回答
1

根据这个

https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html

每个 Web 应用程序都有自己的类加载器,因此单例对于一个应用程序来说是唯一的,并且对另一个应用程序不可见

于 2019-12-07T14:59:08.607 回答
0

当您创建一个 Singleton 实例时,所有请求实例将为其使用的当前类加载器共享同一个实例。

于 2012-07-06T08:59:55.760 回答
0

由于所有Servlets运行在一个运行在单个 的网络服务器上JVM,因此所有 servlet 将只有一个Singelton对象。

于 2012-07-06T09:07:59.047 回答