不,它不会创建“Single”的多个副本。(稍后会访问 Classloader 问题)
您概述的实现在 Briant Goetz 的书“ Java Concurrency in Practice ”中被描述为“Eager Initialization ”。
public class Single
{
private static Single theInstance = new Single();
private Single()
{
// load properties
}
public static Single getInstance()
{
return theInstance;
}
}
但是,代码不是您想要的。您的代码在创建实例后尝试执行延迟初始化。这要求所有客户端库在使用之前执行“firstTime()/doPreparation()”。您将依赖客户端做正确的事情,这使得代码非常脆弱。
您可以将代码修改如下,这样就不会出现任何重复的代码。
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;
}
}
不幸的是,这是延迟初始化的糟糕实现,并且在并发环境(如 J2EE 容器)中不起作用。
有很多关于 Singleton 初始化的文章,特别是关于内存模型的文章。 JSR 133解决了 Java 1.5 和 1.6 中 Java 内存模型的许多弱点。
对于 Java 1.5 和 1.6,您有多种选择,它们在Joshua Bloch的“ Effective Java ”一书中提到。
- Eager Initialziation,如上[EJ Item 3]
- Lazy Initalization Holder 类成语 [EJ Item 71]
- 枚举类型 [EJ 项目 3]
- 带有“volatile”静态字段的双重检查锁定 [EJ Item 71]
解决方案 3 和 4 仅适用于 Java 1.5 及更高版本。所以最好的解决方案是#2。
这是伪实现。
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;
}
}
请注意,'doPreparation()' 在构造函数内部,因此您可以保证获得正确初始化的实例。此外,您正在利用 JVM 的延迟类加载,并且不需要任何同步“getInstance()”。
您注意到静态字段 theInstance不是“最终”的一件事。 Java Concurrency 上的示例没有“final”,但 EJ 有。也许詹姆斯可以为他对“类加载器”的回答和“最终”的要求添加更多颜色以保证正确性,
话虽如此,使用“静态最终”有一个副作用。当 Java 编译器看到“static final”并尝试尽可能地内联它时,它会非常激进。Jeremy Manson 的博客文章中提到了这一点。
这是一个简单的例子。
文件:A.java
public class A
{
final static String word = "Hello World";
}
文件:B.java
public class B
{
public static void main(String[] args) {
System.out.println(A.word);
}
}
编译 A.java 和 B.java 之后,将 A.java 更改为以下。
文件:A.java
public class A
{
final static String word = "Goodbye World";
}
您重新编译“A.java”并重新运行 B.class。你会得到的输出是
Hello World
至于类加载器问题,答案是肯定的,你可以在多个类加载器中拥有多个 Singleton 实例。您可以在wikipedia上找到更多信息。还有一篇关于Websphere的具体文章。