单例模式之静态内部类和双重校验的实现方式
单例模式有实现方式有懒汉式和饿汉式两种,而懒汉式又面临线程安全问题。在这里学习一下单例模式的两种经典的实现方式:InnerClass和DubbleCheck
静态内部类实现单例模式:
静态内部类不会随着外部类的加载而加载 ,只有静态内部类的静态成员被调用时才会进行加载 , 这样既保证的惰性初始化,又由JVM保证了多线程并发访问的正确性。
public class Singletion {
private static class InnerSingletion {
private static Singletion single = new Singletion();
}
public static Singletion getInstance(){
return InnerSingletion.single;
}
}
双重校验的实现方式
public class DubbleSingleton {
private static DubbleSingleton ds;
public static DubbleSingleton getDs(){
if(ds == null){
synchronized (DubbleSingleton.class) {
//这里的判断空一定要写,如果这里不进行判断空,则一定会出现线程安全问题,
if(ds == null){
ds = new DubbleSingleton();
}
}
}
return ds;
}
}
第二次判空是防止多线程情况下发生以下情况:
a.假设:线程A已经经过第一次判断,判断singleton=null,准备进入同步代码块.
b.此时线程B获得时间片,犹豫线程A并没有创建实例,所以,判断singleton仍然=null,所以线程B创建了实例singleton。
c.此时,线程A再次获得时间片,犹豫刚刚经过第一次判断singleton=null(不会重复判断),进入同步代码块,这个时候,我们如果不加入第二次判断的话,那么线程A又会创造一个实例singleton,就不满足我们的单例模式的要求,所以第二次判断是很有必要的。