单例和公共静态变量 Java
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13724230/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
singleton and public static variable Java
提问by Achow
I have 2 options:
我有两个选择:
Singleton Pattern
class Singleton{ private static Singleton singleton = null; public static synchronized Singleton getInstance(){ if(singleton == null){ singleton = new Singleton(); } return singleton; } }
using a
static final
fieldprivate static final Singleton singleton = new Singleton(); public static Singleton getSingleton() { return singleton; }
单例模式
class Singleton{ private static Singleton singleton = null; public static synchronized Singleton getInstance(){ if(singleton == null){ singleton = new Singleton(); } return singleton; } }
使用
static final
字段private static final Singleton singleton = new Singleton(); public static Singleton getSingleton() { return singleton; }
Whats the difference? (singlethreaded or multithreaded)
有什么不同?(单线程或多线程)
Updates: I am aware of Bill Pugh or enum
method.
I am not looking for the correct way, but I have only used 1. Is there really any difference b/w 1 or 2?
更新:我知道 Bill Pugh 或enum
方法。我不是在寻找正确的方法,但我只使用了 1。b/w 1 或 2 真的有什么区别吗?
采纳答案by assylias
The main difference is that with the first option , the singleton will only be initialised when getInstance
is called, whereas with the second option, it will get initialized as soon as the containing class is loaded.
主要区别在于,对于第一个选项,单例只会在getInstance
被调用时初始化,而对于第二个选项,它会在包含类加载后立即初始化。
A third (preferred) option which is lazy and thread safe is to use an enum:
惰性且线程安全的第三个(首选)选项是使用枚举:
public enum Singleton {
INSTANCE;
}
回答by Aviram Segal
There is one difference:
有一个区别:
Solution 1 is a lazy initialization, the singleton instance will be created on the first invoke of getInstance
解决方案 1 是延迟初始化,单例实例将在第一次调用时创建 getInstance
Solution 2 is a eager initialization, the singleton instance will be create when the class loades
方案二是eager初始化,类加载时会创建单例
They both are thread safe, calling the second one multi threaded is a little misleading
它们都是线程安全的,调用第二个多线程有点误导
回答by irreputable
The 1st solutions appears to be lazier, but actually not.
第一种解决方案似乎更懒惰,但实际上并非如此。
A class is initialized when a static method/field is accessed for the 1st time.
第一次访问静态方法/字段时初始化类。
It's likely that getInstance()
is the only publicly accessible static method/field of the class. That's the point of singleton.
这很可能getInstance()
是该类中唯一可公开访问的静态方法/字段。这就是单例的意义所在。
Then the class is initialized when someone calls getInstance()
for the 1st time. That means the two solutions are essentially the same in laziness.
然后当有人getInstance()
第一次调用时初始化该类。这意味着这两种解决方案在惰性方面基本相同。
Of course, the 2nd solutions looks better and performs better.
当然,第二个解决方案看起来更好,性能更好。
回答by John B
So, with the update both options above are thread-safe. However the synchronized
option requires each thread that calls instance
to acquire this lock thereby reducing performance if this is done a lot. Also, using synchronized
at the method level has the potential issue of using a publicly available lock (the class itself) that therefore if some thread acquires this lock (which it could) you could end up with deadlock. The static final
option is more performant but does not do lazy initialization of the singleton (which might not be an issue depending on the system).
因此,通过更新,上述两个选项都是线程安全的。然而,该synchronized
选项要求调用instance
获取此锁的每个线程如果这样做会降低性能。此外,synchronized
在方法级别使用具有使用公开可用锁(类本身)的潜在问题,因此如果某些线程获取此锁(它可能),您可能会以死锁告终。该static final
选项的性能更高,但不会对单例进行延迟初始化(这可能不是问题,具体取决于系统)。
Another option that allows thread-safe lazy init of the Singleton is as follows:
另一个允许单例线程安全延迟初始化的选项如下:
public class MySingleton{
private static class Builder{
private static final MySingleton instance = new MySingleton();
}
public static MySingleton instance(){
return Builder.intance;
}
}
This works because the static inner class is guarenteed to be initialized before any method in the containing class is executed.
这是有效的,因为在执行包含类中的任何方法之前,保证静态内部类被初始化。
回答by Costi Ciudatu
Singleton implementation in Java (if you really want that) can be performed in a more elegant way than you described for both eager and lazy initialization. Check the enum waydescribed by Joshua Bloch and the SingletonHolder solutionproposed by Bill Pugh respectively.
Java 中的单例实现(如果你真的想要的话)可以以比你描述的急切初始化和延迟初始化更优雅的方式执行。分别检查Joshua Bloch 描述的 enum 方式和Bill Pugh 提出的 SingletonHolder 解决方案。
The wikipedia article is also a good start for understanding the pattern and does answer your question.
维基百科文章也是理解模式的良好开端,并且确实回答了您的问题。