在哪个域中有 Java 单例的单个实例?

In what domain is there a single instance of a Java singleton?

根据定义,Java 单例 class 可以有一个实例。当然,除了明显有几个,包括相同的代码 运行ning 在不同的物理机、虚拟机、Java 虚拟机上。

保险的是一个JVM单例单例class?

Java 单例 class 在哪个域中是唯一的?与应用的概念有什么关系,不管它是什么意思?与托管 JVM 的操作系统中的进程或线程的概念有什么关系? Web 服务器中的用户连接?如果我们谈论 Apache 或 Tomcat,它会改变吗?


我设计了一个Java class 提供给其他软件开发人员,他们将通过它访问远程功能。该功能在多台远程机器上冗余实现。 class 保留这些机器的列表,跟踪它们的响应时间,并确保从其调用者收到的请求被发送到当前响应最快的远程机器。这是一个很好的单例用例。

对于其他开发人员如何称呼我的 class 我只有一个模糊的概念。我知道那将是一个网络服务器,由最终用户访问。我知道其他软件开发人员的代码是用 Java 编写的(因为我替换的代码是 C 并从 JNI 调用)。他们谈论从他们在同一台机器上制作的几个应用程序调用我的代码,但我不知道这到底是什么意思。肯定有一些 运行 他们的网络服务器在 Tomcat 上,在同一台服务器上有多个应用程序。另一个显然倾向于 Apache Web Server,还有一个提到了 NGINX。我对他们的工作了解得越少越好。

我知道我的代码将 运行 在同一台机器上的相对较少的 JVM 实例中(如 top 所示),我可以对我的单例实例感到满意。如果 Web 服务器的每个最终用户有 1 个单例,那将是一个严重的问题,一个温和的问题是每个“应用程序”有一个。我想在设计阶段就知道,而不是在现场发现。

通常,class 加载程序只将每个 class 的一个实例加载到内存中。因此,每个 Java VM 所有静态变量只存在一次。

但在 Web 应用程序中(例如在 Apache Tomcat 或类似应用程序中)它有点不同,因为每个应用程序都有自己的 class 加载器,并且还有另一个 class 加载器用于共享库.

当您的 Tomcat 运行两个包含相同库的应用程序(在 *.war 内)时,您实际上在内存中拥有相同库的两个实例,因此它们的静态变量存在两次.但是当两个应用程序共享 lib 文件夹中的库时,内存中只有一个实例。

但是,通过实施自定义 class 加载程序,您可以改变该行为,然后由您决定。

除非您编写自己的 class 具有线程特定功能的加载程序,否则线程通常不会对此产生影响。