这是一个例子:
http://www.tutorialspoint.com/java/java_using_singleton.htm
在查看第一个示例时,当用户编写 : 时Singleton.getInstance()
,它会调用 :
new Singleton()
我不明白,当它每次创建一个新的单例对象时,它是如何单例的?
我理解第二个例子。如果singleton
为null,则创建新对象,但在第一个示例中,它总是创建新对象??
那是怎么回事?
这是一个例子:
http://www.tutorialspoint.com/java/java_using_singleton.htm
在查看第一个示例时,当用户编写 : 时Singleton.getInstance()
,它会调用 :
new Singleton()
我不明白,当它每次创建一个新的单例对象时,它是如何单例的?
我理解第二个例子。如果singleton
为null,则创建新对象,但在第一个示例中,它总是创建新对象??
那是怎么回事?
不,在第一个示例中,唯一的调用new Singleton()
是在这里(在 内Singleton
):
private static Singleton singleton = new Singleton( );
那是一个静态变量初始化器。它执行一次,并且仅在需要时执行。(如果你从不接触这个Singleton
类,初始化器就不会被执行。)
在第二个例子中,正如有人提到的,它不是线程安全的。以下是使 getInstance() 方法线程安全的两个选项:
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized(Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
该方法的第二个版本允许您在没有任何同步开销的情况下获取已经构建的单例实例。但是,当它为空时,您将输入一个同步块。您再次检查 null 以防万一发生线程上下文切换,并且第二个线程实际上在您之前进入了同步块。这样可以确保只构建一个实例。
任何一种方法都应该是完全线程安全的。
仅在new Singleton()
加载类时才被调用。
该成员singleton
被声明为静态的,因此new Singleton()
只被调用一次。
该行:
private static Singleton singleton = new Singleton( );
仅在加载类时执行一次——它是一个类字段初始值设定项。
看看这个问题:最佳实践:在构造函数或声明时初始化类字段?- 与那个问题中的想法相同new Random()
。
编辑:我突然进入 Stack Overflow 一会儿,看看我是否可以回答一个未回答的问题,在我提交回复之前,看起来其他三个人已经回答了它。我喜欢堆栈溢出!