这个Java单例可以在WebSphere6中重复重建吗?
我正试图追踪我们系统中的一个问题,下面的代码让我担心。在主servlet中的doPost()方法中出现以下情况(名称已更改以保护用户): 单身“单身”看起来像这样:这个Java单例可以在WebSphere6中重复重建吗?,java,singleton,instance,Java,Singleton,Instance,我正试图追踪我们系统中的一个问题,下面的代码让我担心。在主servlet中的doPost()方法中出现以下情况(名称已更改以保护用户): 单身“单身”看起来像这样: private static Single theInstance = new Single(); private Single() { ...load properties... } public static Single getInstance() { return theInstance; } 通过将其设置为使
private static Single theInstance = new Single();
private Single() {
...load properties...
}
public static Single getInstance() {
return theInstance;
}
通过将其设置为使用静态初始值设定项而不是在getInstance()方法中检查null实例的方式,是否可以一次又一次地重新构建它
PS-我们在Java 1.4上运行WebSphere 6,该应用程序不会一次又一次地构建。它是静态的,所以只在类加载器第一次接触类时构造一次 唯一的例外-如果您碰巧有多个类加载器 (发件人):
否-实例的静态初始化只会执行一次。需要考虑两件事:
- 这不是线程安全的(实例未“发布”到主存)
- 除非正确同步,否则您的
方法可能会被多次调用firstTime
MySingleton
类实际上是
不同的(请参阅“类装入器作为
参考资料中的名称空间机制。)
因为两个单例对象属于
两个同名的类,它将
乍一看似乎有
两个相同的单例对象
班级
除上述问题外,如果未同步
firstTime()
,也可能存在线程问题。理论上它只会生成一次。但是,这种模式在各种应用服务器中都会出现,在这些服务器中可以获得多个“singleton”类的实例(因为它们不是线程安全的)
此外,单例模式也受到了很多批评。例如,请参见,我唯一要更改的关于单例实现的事情(除了根本不使用单例)是将实例字段设置为final。静态字段将在类加载时初始化一次。由于类是惰性加载的,所以实际上可以免费获得惰性实例化 当然,如果它是从单独的类装入器装入的,那么会得到多个“单例”,但这是Java中每个单例习惯用法的一个限制
编辑:firstTime()和dopreparions()位看起来确实可疑。难道不能将它们移动到singleton实例的构造函数中吗?正如其他人所提到的,静态初始值设定项只会在每个类加载器中运行一次 我想看一看的是
firstTime()
方法-为什么dopreparions()
中的工作不能在singleton本身中处理
听起来像是一组令人讨厌的依赖项。当类加载器加载类时,只会加载一次。 这个例子提供了一个更好的单例实现,但是,它尽可能地延迟加载并且线程安全。 此外,它可以在所有已知的Java版本中工作。 此解决方案是跨不同Java编译器和虚拟机的最具可移植性的解决方案
public class Single {
private static class SingleHolder {
private static final Single INSTANCE = new Single();
}
private Single() {
...load properties...
}
public static Single getInstance() {
return SingleHolder.INSTANCE;
}
}
内部类的引用时间不早于调用getInstance()的时间(因此类加载器的加载时间也不早于此)。因此,该解决方案是线程安全的,不需要特殊的语言构造(即volatile和/或synchronized) 使用静态初始值设定项和延迟初始化之间绝对没有区别。事实上,更容易搞乱延迟初始化,这也会强制同步。JVM保证静态初始值设定项总是在访问类之前运行,并且只会发生一次 也就是说,JVM不能保证类只加载一次。但是,即使它被多次加载,您的web应用程序仍将只看到相关的单例,因为它将被加载到web应用程序类加载器或其父类中。如果部署了多个web应用程序,则将为每个应用程序调用firstTime()
要检查的最明显的事情是firstTime()需要同步,并且在退出该方法之前设置了firstTime标志。否,它不会创建“Single”的多个副本。(稍后将访问类加载器问题) 您概述的实现在Briant Goetz的书-''中被描述为“急切的初始化” 但是,代码不是您想要的。您的代码试图在创建实例后执行延迟初始化。这要求所有客户端库在使用它之前执行“firstTime()/dopreparion()”。您将依靠客户进行ri
public class Single {
private static class SingleHolder {
private static final Single INSTANCE = new Single();
}
private Single() {
...load properties...
}
public static Single getInstance() {
return SingleHolder.INSTANCE;
}
}
public class Single
{
private static Single theInstance = new Single();
private Single()
{
// load properties
}
public static Single getInstance()
{
return theInstance;
}
}
public class Single
{
private static Single theInstance = new Single();
private Single()
{
// load properties
}
public static Single getInstance()
{
// check for initialization of theInstance
if ( theInstance.firstTime() )
theInstance.doPreparation();
return theInstance;
}
}
public class Single
{
private static class SingleHolder
{
public static Single theInstance = new Single();
}
private Single()
{
// load properties
doPreparation();
}
public static Single getInstance()
{
return SingleHolder.theInstance;
}
}
public class A
{
final static String word = "Hello World";
}
public class B
{
public static void main(String[] args) {
System.out.println(A.word);
}
}
public class A
{
final static String word = "Goodbye World";
}
Hello World
private USDateFactory () { }
public static USDateFactory getUsdatefactory() {
if(usdatefactory==null) {
usdatefactory = new USDateFactory();
}
return usdatefactory;
}
public String getTextDate (Date date) {
return null;
}
public NumericalDate getNumericalDate (Date date) {
return null;
}