美文网首页
【Java】设计模式之单例模式

【Java】设计模式之单例模式

作者: renkuo | 来源:发表于2018-04-23 17:24 被阅读25次

    工作有几年了,但是好多东西感觉没有沉淀下来,设计模式平时都在用,一些代码的技巧都是通过经验累积起来的,但是总感觉缺少一定的体系。很多东西会写,但是不会说,这就很尴尬。所以很多东西都要适当的整理一下,理论还是不能缺少的。比方说有人问你java特性,但是有的时候你可能一瞬间真的就卡住了,没办法通过专业名词表达出来。最近下定决心,花几个月的时间,把java的设计模式都整理出来。今天先整理一个个人认为大家都在用,而且比较经典的单例模式。不足之处欢迎大家指出,共同进步!∩▂∩站在巨人的肩膀上不停进步,哈哈。

    UML类图

    image.png

    单例模式

    双重检查加锁单例
    如果性能是你关注的重点,这个做法可以大大地减少getInstance()的时间消耗。
    因为这种方法并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法后,先检查实例是否存在,如果不存在才进行下面的同步块,这是第一重检查,进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

    public class Singleton {
    //volatile关键词确保:当uniqueInstance变量被初始化成Singleton实例时,多线程正确处理uniqueInstance变量
        private volatile static Singleton uniqueInstance;
        private Singleton(){}
        public static Singleton getInstance(){
            if (uniqueInstance == null){
                synchronized (Singleton.class){
                    if (uniqueInstance ==null){
                        uniqueInstance = new Singleton();
                    }
                }
            }
            return uniqueInstance;  
    }
    

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

    public class Singleton {
        private Singleton(){}
        /**
         *    类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
         *    类级内部类相当于其外部类的成员,只有在第一次被使用的时候才被会装载
         */
        private static class SingletonHolder{
            /**
             * 静态初始化器,由JVM来保证线程安全
             */
            private static Singleton instance = new Singleton();
        }
        public static Singleton getInstance(){
            return SingletonHolder.instance;
        }
    }
    

    枚举单例
    单例的枚举实现在《Effective Java》中有提到,因为其功能完整、使用简洁、无偿地提供了序列化机制、在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化。这种方法的单例被认为是最好的单例。

    public enum SingletonSourceEnum {
        INSTANCE;
    
        private Singleton1 singleton1;
        private SingletonSourceEnum() {
            singleton1 = new Singleton1();
        }
        public Singleton1 getInstance() {
            return singleton1;
        }
    }
    
    public class Singleton1 { }
    

    验证方式如下:system.out输出的是true,结果表明两次获取的是一次实例

    Singleton1 singleton1 = SingletonSourceEnum.INSTANCE.getInstance();
    Singleton1 singleton2 = SingletonSourceEnum.INSTANCE.getInstance();
    System.out.println(singleton1 == singleton2);
    

    饿汉式单例
    饿汉式是典型的空间换时间,当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断,节省了运行时间。

    
    public class Singleton2 {
    
        private static Singleton2 singleton = new Singleton2();
    
        private Singleton2(){}
    
        private static Singleton2 getInstance(){
    
            return singleton;
        }
    }
    
    

    懒汉式单例
    懒汉式是典型的时间换空间,由于懒汉式的实现是线程安全的,这样会降低整个访问的速度,而且每次都要判断,比较浪费时间。

    public class Singleton3 {
    
        private static Singleton3 singleton ;
    
        private Singleton3(){}
    
        private static synchronized Singleton3 getInstance(){
            if (singleton == null){
                singleton = new Singleton3();
            }
    
            return singleton;
        }
    }
    

    错误不足之处或相关建议欢迎大家评论指出,谢谢!如果觉得内容可以的话麻烦喜欢(♥)一下

    相关文章

      网友评论

          本文标题:【Java】设计模式之单例模式

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