单例模式总结

昨天翻了本设计模式的书,发现单例模式竟然有点弄不明白了,抓紧查资料补上,这里总结下。

1:

class Singleton
{
private static Singleton instance;
private Singleton()
{
//
}

public static Singleton getInstance()
{
if (instance == null)
instance
= new Singleton();
return instance;
}
}

注意:构造函数私有,方法静态

问题:无法保证线程安全,有多个线程访问getInstance方法的时候可能产生多个Singleton对象。

2:

可以给getInstance方法添加同步:

public static synchronized Singleton getInstance()
{
if (instance == null) //1
instance = new Singleton(); //2
return instance; //3
}

这样能满足需求,但是会带来性能上的损失。一般同步的方法比非同步的方法效率要低上百倍

3:

然后是懒汉式的单例模式:

class Singleton
{
private static Singleton instance = new Singleton();
private Singleton()
{
//
}

public static Singleton getInstance()
{
return instance;
}
}

这种方法能保证instance实例在Singleton类第一次加载的时候初始化,解决了同步问题

进一步的要求可能是不想让instance对象在类加载的时候初始化,而在使用getInstance方法的时候才初始化

4:

双重锁

public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
}

这种方法能保证instance只被初始化一次。但是由于JVM内部的问题,该方法还是有漏洞的。

假设线程1进入到步骤2,执行步骤3未完成,会先将instance设为非null值。

这时候线程2会在判断instance==null的时候失败,返回一个不完整的intance对象

5:

既要lazy loading,又要同步~

Bob Lee提出了一种方法:

public class Singleton {
private Singleton(){
}
static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}

在该方法中,Singleton有一个静态内部类,内部类在外部类加载的时候并不会加载,只有在调用getInstance方法的时候加载SingletonHolder类。

如上面的程序还是可能有问题:

Singleton.SingletonHolder sh = new Singleton.SingletonHolder();
Singleton instance
= Singleton.SingletonHolder.instance;
instance
= sh.instance;

上面的代码是可以访问SingletonHolder的内容的~~

所以进一步的把SingletonHolder设为private的应该会更好。

所以最后的代码如下:

public class Singleton {
private Singleton(){
}
private static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
public static void main(String [] args)
{
Singleton.getInstance();
}
}

原文地址:https://www.cnblogs.com/macula7/p/2003225.html