下面的代码片段中有两个Singleton的实现。它们是否都是在Java多线程环境中实现单例的正确方法?
如果是这样的话,这是否意味着第二种实现方式是完全无用的,并且当您想要实现单例时,只需使用枚举方式?。
我的独白写法是:
public enum Singleton {
INSTANCE();
}另一种编写Singleton (显式同步)的方法:
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instanz == null) {
instanz = new Singleton();
}
return instanz;
}发布于 2015-07-16 16:33:37
一些程序员讨论如何创建单个程序的原因是,他们希望支持延迟创建,但担心访问器方法的后续调用的性能。
因此,使用synchronized的类实现了延迟创建方面,但随后的调用可能会受到synchronized不必要的开销的影响。为了克服这种假想的开销,发明了臭名昭著的双重检查锁,这引发了更多关于这个“问题”的讨论,而这个问题实际上是完全不相关的:
如果要将惰性创建与单个实例结合起来,则只需使用:
public class Singleton {
static final Singleton INSTANCE=new Singleton();
private Singleton(){}
public static Singleton getInstance() {
return INSTANCE;
}
}整个构造是延迟的,因为类初始化不会在第一个线程调用getInstance()之前发生,并且它是线程安全的,因为JVM保证类初始化本身是线程安全的。这是最有效的解决方案,因为后续调用将只读取一个final字段,而不需要同步。
这正是使用
public enum Singleton {
INSTANCE;
}它可以避免像编译器那样声明private构造函数。这个字段是隐式的static final。一个不同之处是,字段本身是公开的,不需要访问器方法。
此外,enum支持系列化,本质上。存储常量时,不存储实例数据,只存储类型和常量名称。反序列化之后,将查找当前运行时实例。因此,如果您需要序列化支持,应该首选enum,否则没有太大的差别(使用enum保存一些类型)。
但
简单地说,单例设计模式似乎被严重高估了,并且讨论了如何高效地实现它,甚至更多的…。
发布于 2015-07-16 14:07:31
你们俩看起来都很好。但是,对于创建Singleton,我将建议采用以下方法,即100%线程安全,没有同步问题,因为利用了Java的类加载机制.
注:扣动扳机的功劳是“詹姆斯”。
Lazy singleton:
与此类似,类提供程序只加载一次,因此只有一个Network类实例,没有两个线程可以在同一个JVM中创建2个实例,因为类不会加载两次。
优势:
getInstance()时,不需要承担同步的成本,当存在具有同步的getInstance()时,就会发生这种情况。急切的单身人士:
private static Network INSTANCE = null;
private Network(){
}
static {
INSTANCE = new Network();
}
public static Network getInstance() {
return INSTANCE;
}最后,:您得到了正确的第二种方法,您指定的第二种方法实际上是最后一种选择,因为每次有两个线程试图获取单例实例时,它都必须承担同步的成本。
现在,它的游戏v/s懒惰的单身汉。我提供了几个关于为什么人们不喜欢ENUM的链接,以及基于类加载的ENUM单例、v/s惰性单例的可伸缩性。
这两种方法都会无缝地工作,因此它的选择问题,因此真正的答案是“这取决于!”
发布于 2015-07-16 13:54:00
两者都是线程安全的,但是第一个使用枚举,可以避免不必要的锁定,并且在大多数情况下都更可取。
https://stackoverflow.com/questions/31456178
复制相似问题