Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这个Java单例可以在WebSphere6中重复重建吗?_Java_Singleton_Instance - Fatal编程技术网

这个Java单例可以在WebSphere6中重复重建吗?

这个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; } 通过将其设置为使

我正试图追踪我们系统中的一个问题,下面的代码让我担心。在主servlet中的doPost()方法中出现以下情况(名称已更改以保护用户):

单身“单身”看起来像这样:

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
    方法可能会被多次调用

我在Sun的网站上找到了这个:

由不同类装入器同时装入的多个单例 当两个类装入器装入一个类时, 实际上你有两份 类,每个类都可以有自己的 单例实例。就是 在servlet中特别相关 在某些servlet引擎中运行 (例如iPlanet),其中 默认情况下,servlet使用自己的类 加载器。两个不同的servlet 访问联合单例将 事实上,得到两个不同的对象

多类装入器的出现频率更高 比你想象的要普遍。什么时候 浏览器从网络加载类 对于小程序,它们使用 每个服务器都有单独的类加载器 地址。类似地,Jini和RMI 系统可以使用单独的类 不同代码基的加载程序 他们从中下载类文件。 如果您自己的系统使用自定义类 装载机,同样的问题可能会发生 起来

如果由不同的类装入器装入, 两个同名的类,偶数 相同的包名,则被视为 不同——即使事实上,它们是不同的 同一类中的逐字节。这个 不同的类装入器表示 不同的名称空间可以区分 类(即使类是 名称相同),因此
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;
}