美文网首页
设计模式之单例模式(1)

设计模式之单例模式(1)

作者: Johnson_Coding | 来源:发表于2019-11-14 14:48 被阅读0次

    优点:1.减少内存开支
    2.减少性能开销
    3.避免对一个西苑的多重占用
    4.便于全局访问
    缺点:
    1.没有接口扩展困难
    2.单例持有Context容易造成内存泄露,所以推荐使用Application的Context。

    饿汉式(不管吃不吃得下,先把碗装满)
    public class HungrySingleton{
    private static final HungrySington intance = new HungrySingleton();
    private HungrySingleton(){}
    public static HungrySington getIntance(){
         return intance;
    }
    }
    

    1.线程安全。利用了类的加载机制,加载初始化静态变量,且被只会执行一次,且JVM会利用锁来同步多个线程对同一个类的初始化。这样就保证了构造方法只会调用一次。
    2.不能懒加载。无论是否使用都会去初始化实例。

    懒汉式(需要的时候再去获取)
    public class LazySingleton{
    private static final LazySingleton intance = null;
    private LazySingleton(){}
    public static LazySingleton getIntance(){
       if(intance == null){
          intance  = new LazySingleton();
    }
       return intance;
    }
    }
    

    优点是可以实现延迟加载。在类初次加载的时候,由于只是声明了这个静态的对象,但不会自动初始化 instance对象,所以称为懒汉式

    缺点是线程不安全。多线程并发无法保证唯一的实例改进策略:需要保证线程安全

    双重检查锁(在需要创建对象的时候再进行同步锁操作,即如果实例对象已经创建,那么多线程的状态下可以同时获取到实例对象)
    public class DoubleCheckSingleton{
    private volatile static DoubleCheckSingleton intance;
    private  DoubleCheckSingleton(){}
    public  static DoubleCheckSingleton getInstance(){
     if(instance == null){
    synchronized(DoubleCheckSingleton .class){
          if(instance == null){
               intance = new DoubleCheckSingleton();
    }
          return intance;
    }
    }
    }
    }
    
    1. 这种策略看似解决了每次都需要同步的问题,但是由于 instance = new DclSingleton(); 这个初始化是非原子性的操作(1,给实例分配内存,2,调用构造函数初始化成员字段,3,实例对象指向分配的内存空间 23不能保证顺序执行)。就是说这个在JVM中可能会分成几步执行,那么就会存在指令重排序的问题,所以需要继续改进:添加 volatile 关键字。
    2. 改进后,懒加载
    3. 线程安全

    当声明对象的引用为volatile后,初始化中的重排序,在多线程环境中将会被禁止,从而在根本上解决了问题。但是volatile在jdk1.5以后才能正确工作。

    原因看[volatile关键字的使用]

    静态内部类
    public class StaticInnerSingleton{
          public static StaticInnerSingleton getIntance(){
          return SingletonHolder.instance;
    }
          private StaticInnerSingleton(){}
          private static class SingletonHolder{
                private static final StaticInnerSingleton instance = new StaticInnerSingleton ();
    }
    }
    

    当第一次加载Singleton类时不会初始化instance,只有在调用了getSingleton方法的时候才会触发instance被初始化。因此,第一次调用get'Singleton方法会导致虚拟机加载SingletonManager类,这种方式不仅能确保线程安全,也能保证单例对象的唯一性,同时也延迟了单例的实例化。所以单例模式推荐使用这种方式实现)

    相关文章

      网友评论

          本文标题:设计模式之单例模式(1)

          本文链接:https://www.haomeiwen.com/subject/rydrictx.html