1、什么是单例模式
简单来说,单例模式就是一个类只能构建一个对象的设计模式。
2、单例模式第一版:
public class Singleton_V1{
private Singleton_V1(){}//私有构造函数
private static Singleton_V1 instance=null;//单例对象
//静态工厂方法
public static Singleton_V1 GetInstance(){
if(instance==null){
instance=new Singleton_V1();
}
return instance;
}
}为什么这样写,下面我们来解释一下:
1、要想让一个类只能构建一个对象,就不能让其随便的去做new操作,因此Singleton_V1的构造方法是私有的。
2、instance是Singleton_V1类的静态成员,也就是我们的单例对象。他的初始值可以写成null,也可以写成new Singleton_V1().
3、getInstance()是获取单例对象的方法。
如果单例初始值是null,还未构建,则构建单例对象并返回。这个写法即是private static Singleton instance=null;的方式。也叫懒汉模式。
如果单例对象一开始就被new Singleton()主动构建。则不再需要做判空的操作。这个写法即是private static Singleton instance=new Singleton();的方式,也就是上文所说的instancec初始值可以为null,也可以为new Singleton()的区别。也叫饿汉模式。
3、单例模式第二版
第一版的写法虽然实现了单例模式,但是并不是线程安全的,因为假如Singleton类刚刚被初始化,instance对象还是空,这时候两个线程同时访问getInstance方法:
由上图可知:此时因为Instance是空,所以两个线程同时通过了判断,开始执行new操作,这样的话,instance就会被构建了两次。所以,要想线程安全的话,我需要对代码做进一步的优化。
单例模式第二版:
public class Singleton_V2{
private Singleton_V2(){}//私有函数构造
private static Singleton_V2 instance=null;//单例对象
//静态工厂方法
public Singleton_V2 GetInstance(){
if(instance==null){//双重检测机制
lock(Singleton_V2.class){//同步锁
if(instance==null){
instance=new Singleton_V2();
}
}
}
return instance;
}
}根据以上代码我们来解释为什么这样写就是线程安全的:
1、为了防止new Singleton被执行多次,因此在new操作之前加上lock同步锁,锁住整个类
2、进入lock临界区以后,还要在做一次判空。因为当两个线程同时被访问的时候。线程A构建完对象,,线程B也已经通过了最初的判空验证,不做第二次判空的话,线程B还是会再次构建instance对象。