2013-07-18 68 views
15

如果我在Tomcat(或任何其他服务器)的单个实例上部署并运行同一应用程序的2个实例。然后(一个Singleton类的)的单个对象将被创建:跨JVM或应用程序实例或Tomcat实例的单身

  1. 对面的Tomcat的单个实例(但常见的同一应用程序的2个实例)OR
  2. 跨应用程序的实例(用于应用程序的2个实例不同)

所以基本上我想明白,每个JVM都会创建Singleton类的单个对象吗?在Web服务器(或容器)上托管应用程序的情况下,这是如何工作的。

回答

23

如果你有一个singleton类,并且运行两个在Tomcat中使用这个类的webapps,那么这两个webapps将在运行Tomcat的JVM中得到这个单例的两个不同实例。

但是,如果您的webapp将使用来自JRE或Tomcat共享库的单例,例如Runtime.getRuntime webapps将获得相同的Runtime实例。

这是因为Tomcat为webapps使用单独的类加载器。当一个webapp类加载器加载一个类时,它首先尝试在webapp类路径上找到它,如果该类未找到,它会要求父类加载器加载该类。

+2

@Evgenniy,这是否意味着在我的单个应用程序中,我可以使用不同的类加载器创建2个单例对象(只是一个想法)。 – Learner

+1

是的,创建2个类加载器(你可以使用URLClassLoader),用ClassLoader.loadClass(className)加载同一个类 - 你将得到2个不同的类实例 –

+0

这是否意味着Singleton被破坏? – Learner

1

<shakey-ground>就我所知,每个类加载器都有一个单例是唯一的。所以我认为你的问题的答案取决于容器加载Web应用程序的方式。

如果它为每个Web应用程序分配一个类加载器,那么看起来你会得到两个完全独立的单例对象。如果它分配了一个类加载器并且所有Web应用程序都使用它,那么它们共享相同的单独一个实例。 </shakey-ground>

14

单身人士通常只与ClassLoader有关。

因此,如果您的.war文件中有一个基于.class文件的单例,并且您多次部署此Web应用程序,则每个应用程序都会获得它自己的单例。另一方面,如果你的单例的.class文件在tomcat的类路径中,那么你只有一个实例。此.class不属于特定的Web应用程序(它属于tomcat实例)。

如果您在两个位置都有单例,它取决于类加载器层次结构,并且您可以选择“父第一”或“第一个Web应用程序”。

+0

@Beryllium“tomcat类路径”的含义是什么?我的意思是我应该在哪里学习我的课程/ jar,这样我就可以跨应用程序获得单身人士。 – Vipin

+0

@vipin我无法确定,因为我最近没做,但是尝试将.jar文件放入tomcat的lib /目录中。至于JBoss 7他们有效地做同样的事情,他们只是把它组织成“模块”。 – Beryllium

+0

@Beryllium long back我读过一篇文章,里面说我们不应该把我们的任何jar放在tomcat/lib中。最近我做了一些研究,发现我们可以使用catalina.properties的shared.loader属性。但不知道它会不会起作用。 – Vipin

4

通过确保您始终为单身人士查询相同的ClassLoader,可以创建这样的单身人士。我在这个其他答案中写了一个extensive explanation

1
  • Tomcat为每个Web应用程序创建新的类加载器。
  • 因此,如果你的Singleton类存储在war文件中,同一个war文件将在Tomcat容器中有两个实例,即它为每个war文件创建两个单独的Singleton类。
  • 如果Singleton类在Tomcat的共享库路径中,那么Tomcat将只为这两个应用程序创建一个Singleton实例。

JVM的比喻:

JVM是喜欢大豪宅。它包含结合家庭与多功能应用程序和图书馆。

ClassLoaders是家庭成员,每个家庭成员代表一个ClassLoader(作为委托层次结构而不是等级层次结构)。注意:ClassLoader是类,它可以创建多个实例。

应用程序就像家电一样。例如:洗衣机,冰箱,冷风机,Telivision,餐桌,沙发等...

图书馆是每个人都有自己的个人图书馆。如果没有找到父母的自由,每个人都要在自己的图书馆里搜索。

限制: 如果父亲购买电器,他们的孩子可以使用它,但不能使用他的父母和兄弟姐妹。 每个应用程序可能使用相同库的不同版本。即如果图书馆包含相同书籍的两个或更多个版本,则它首先选择书籍可用的那一个。

每个家庭号码只能使用一个唯一的设备。

在家中,我们可以使用同一版本的多功能设备。所以,JVM允许我们运行相同版本的多个应用程序。

垃圾收集器是Mansion的一名工作人员,他作为守护进程漫游,可以清除任何类型的对象。

静态变量的作用域限于每个ClassLoader一个。