Java设计模式——懒汉式单例模式

一、懒汉式单例模式

      懒汉式单例模式在被外部类调用时创建实例,因类加载速度快,但运行时获取对象的速度慢

二、实例

1》在方法上使用synchronized锁进行同步,缺点是这个同步方法影响的区域太大,如果多个对象想获取这个对象的时候会柱塞在这排队。

public class LazySingleton{

    private static LazySingleton intance =null;

    private LazySingleton(){}

    
    public static synchronized LazySingleton getInstance(){

        if(instance == null){
            instance = new LazySingleton();
        }
        
        return instance;
    }

}

2》在方法体中使用双重检查锁,节约了内存空间,又保证线程安全。


public class LazySingleton{

    private static LazySingleton instance = null;

    private LazySingleton(){}

    public static LazySingleton getInstance(){

        if(instance == null){
              synchronized(LazySingleton.class){
                    if(instance == null){
                        instance = new LazySingleton();
                    }            
               }
         }
        return instance;
    }
}

   由于jvm存在乱序执行功能,DCL也会出现线程不安全的情况,其实在jvm里面的执行分为三步:

          1.在堆内存开辟内存空间。
          2.在堆内存中实例化SingleTon里面的各个参数。
          3.把对象指向堆内存空间。

       由于jvm存在乱序执行功能,所以可能在2还没执行时就先执行了3,如果此时再被切换到线程B上,由于执行了3,INSTANCE 已经非空了,会被直接拿出来用,这样的话,就会出现异常。这个就是著名的DCL失效问题。

       即在JDK1.6及以后,只要定义为private volatile static LazySingleton instance= null;就可解决DCL失效问题。volatile确保INSTANCE每次均在主内存中读取,这样虽然会牺牲一点效率,但也无伤大雅。

3》使用内部类进行单例


public class Singleton{

    private Singleton(){}

    public Static getInstance(){

        return SingleHolder.instance;
    }

   private class SingleHolder{
         private static Singleton  instance = new Singleton();

    }
}

       在这个实现中,用内部类来保护单例,当Singleton类被加载时,内部类不会被初始化,所以可以确保Singleton类被载入JVM时,不会初始化单例类,当getInstance方法被调用时,才会加载SingleHolder,从而初始化instance,同时,由于实例的建立是在类加载时完成的,故天生对多线程友好,getInstance()方法也不需要使用synchronized修饰,因此,这种实现能兼顾前两种写法的优点(延迟加载,非同步)。

你可能感兴趣的:(Java设计模式)