zoukankan      html  css  js  c++  java
  • 单例模式(三种实现)

    1 饿汉式

    public class EagerSingleton {
    static {
    System.out.println("EagerSingleton 被加载");
    }

    private EagerSingleton(){}  //私有化构造方法,限制直接构造,只能调用 getInstance() 方法获取单例对象


    private static final EagerSingleton eagerSingleton=new EagerSingleton(); // 私有化静态 final成员,类加载直接生成单例对象,比较占用内存 
    public static EagerSingleton getInstance(){  //提供对外的公共api获取单例对象
    return eagerSingleton;
    }

    }

    总结:饿汉式单例的特点:饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成。

    2 懒汉式

    public class LazySingleton {
    static {
    System.out.println("LazySingleton 被加载");
    }

    private LazySingleton(){} //私有化构造方法,限制直接构造,只能调用 getInstance() 方法获取单例对象
    private static LazySingleton lazySingleton=null;//静态域初始化为null,为的是需要时再创建,避免像饿汉式那样占用内存
    public static LazySingleton getInstance(){//提供对外的公共api获取单例对象
    if(lazySingleton==null){ 
    synchronized (LazySingleton.class){ //在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗
    if(lazySingleton==null){
    lazySingleton = new LazySingleton();
    }
    }
    }
    return lazySingleton;
    }

    }

    总结:有同步锁的性能消耗

    3 静态内部类实现

    public class IoDHSingleton {
    static {
    System.out.println("IoDHSingleton 被加载");
    }

    private IoDHSingleton(){} //私有化构造方法,限制直接构造,只能调用 getInstance() 方法获取单例对象


    public static IoDHSingleton getInstance(){//提供对外的公共api获取单例对象
    return HolderClass.ioDHSingleton; //当getInstance方法第一次被调用的时候,它第一次读取HolderClass.ioDHSingleton,内部类HolderClass类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静态域,从而创建ioDHSingleton 的实例,由于是静态的域,                                                            因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性。
    }

    private static class HolderClass{
    static {
    System.out.println("HolderClass 被加载");
    }
    private static IoDHSingleton ioDHSingleton = new IoDHSingleton();
    }

     // 防止反序列化获取多个对象的漏洞  

    private Object readResolve() throws ObjectStreamException {    

    return  HolderClass.ioDHSingleton;  

        }  


    }

    这个模式的优势在于,getInstance方法并没有被同步,并且只是执行一个域的访问,因此延迟初始化并没有增加任何访问成本。

    考虑反射:

      由于在调用 SingletonHolder.instance 的时候,才会对单例进行初始化,而且通过反射,是不能从外部类获取内部类的属性的。

      所以这种形式,很好的避免了反射入侵。

    考虑多线程:

      由于静态内部类的特性,只有在其被第一次引用的时候才会被加载,所以可以保证其线程安全性。

    总结:

      优势:兼顾了懒汉模式的内存优化(使用时才初始化)以及饿汉模式的安全性(不会被反射入侵)。

      劣势:需要两个类去做到这一点,虽然不会创建静态内部类的对象,但是其 Class 对象还是会被创建,而且是属于永久带的对象。

      

  • 相关阅读:
    Python代写使用矩阵分解法找到类似的音乐
    (转)语义分析透镜洞察婚庆微博用户行为数据
    (转)虎扑论坛基因探秘:社群用户行为数据洞察
    bzoj 4922: [Lydsy1706月赛]Karp-de-Chant Number 贪心+dp
    bzoj 1110: [POI2007]砝码Odw 贪心
    bzoj 3721: PA2014 Final Bazarek 贪心
    bzoj 2563: 阿狸和桃子的游戏 贪心
    bzoj 3999: [TJOI2015]旅游 LCT
    bzoj 4240: 有趣的家庭菜园 树状数组+贪心
    CF369E Valera and Queries kdtree
  • 原文地址:https://www.cnblogs.com/zhaoblog/p/8514386.html
Copyright © 2011-2022 走看看