在Java中实现单例设计模式的有效方法是什么?
当前回答
如果您不需要延迟加载,那么只需尝试:
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() { return Singleton.INSTANCE; }
protected Object clone() {
throw new CloneNotSupportedException();
}
}
如果您希望延迟加载并且希望单例是线程安全的,请尝试双重检查模式:
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if(null == instance) {
synchronized(Singleton.class) {
if(null == instance) {
instance = new Singleton();
}
}
}
return instance;
}
protected Object clone() {
throw new CloneNotSupportedException();
}
}
由于双重检查模式不能保证有效(由于编译器的一些问题,我对此一无所知),因此您也可以尝试同步整个getInstance方法或为所有单例创建注册表。
其他回答
如果您不需要延迟加载,那么只需尝试:
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() { return Singleton.INSTANCE; }
protected Object clone() {
throw new CloneNotSupportedException();
}
}
如果您希望延迟加载并且希望单例是线程安全的,请尝试双重检查模式:
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if(null == instance) {
synchronized(Singleton.class) {
if(null == instance) {
instance = new Singleton();
}
}
}
return instance;
}
protected Object clone() {
throw new CloneNotSupportedException();
}
}
由于双重检查模式不能保证有效(由于编译器的一些问题,我对此一无所知),因此您也可以尝试同步整个getInstance方法或为所有单例创建注册表。
忘记延迟初始化;这太有问题了。这是最简单的解决方案:
public class A {
private static final A INSTANCE = new A();
private A() {}
public static A getInstance() {
return INSTANCE;
}
}
Stu Thompson发布的解决方案在Java 5.0及更高版本中有效。但我宁愿不使用它,因为我认为它容易出错。
人们很容易忘记不稳定的说法,也很难理解为什么有必要这样做。如果没有易失性,由于双重检查锁定反模式,该代码将不再是线程安全的。有关这一点的更多信息,请参阅《Java并发实践》第16.2.4段。简而言之:此模式(在Java5.0之前或没有volatile语句)可能返回对Bar对象的引用,该对象(仍然)处于错误状态。
这种模式是为性能优化而发明的。但这真的不再是一个真正的问题了。下面的惰性初始化代码很快,更重要的是,更容易阅读。
class Bar {
private static class BarHolder {
public static Bar bar = new Bar();
}
public static Bar getBar() {
return BarHolder.bar;
}
}
确保你真的需要它。在谷歌上搜索“singleton反模式”,看看反对它的一些论点。
我想这并没有什么本质上的问题,但它只是一种公开某些全局资源/数据的机制,因此请确保这是最好的方法。特别是,我发现依赖注入(DI)更有用,特别是如果您也在使用单元测试,因为DI允许您将模拟资源用于测试目的。
看看这篇文章。
Java核心库中的GoF设计模式示例
从最佳答案的“Singleton”部分,
Singleton(可由每次返回相同实例(通常是其本身)的创建方法识别)java.lang.Runtime#获取运行时间()java.awt.Desktop#getDesktop()java.lang.System#getSecurityManager()
您还可以从Java本机类本身学习Singleton的示例。
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap