美文网首页设计模式
设计模式-单例

设计模式-单例

作者: 漆先生 | 来源:发表于2021-03-28 16:58 被阅读0次

    参考链接:https://www.runoob.com/design-pattern/singleton-pattern.html

    一、单例模式

    单例模式属于创建型模式。一个单一的类,创建自己的对象,同时确保只有单个对象被创建。给外部提供了一种访问其唯一的对象的方法,不再需要实例化该类的对象。

    二、单例模式的常见实现形式

    1.懒汉式,线程不安全

    • 延迟加载,减少内存占用;
    • 线程不安全,没有加锁 synchronized,不能在多线程使用
    public class Singleton {
        private static Singleton instance = null;
    
        private Singleton() {
    
        }
    
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    } 
    

    2.懒汉式,线程安全

    • 延迟加载,减少内存占用
    • 线程安全,但是执行效率低,大部分情况下不需要锁
    public class Singleton {
        private static Singleton instance = null;
    
        private Singleton() {
    
        }
    
        public static synchronized Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    } 
    

    3.饿汉式,线程安全

    • 类加载就初始化,浪费内存。可能被类中其它静态变量方法的调用引起类的初始化
    • 没有加锁,执行效率搞。利用classloader的机制,避免了线程同步的问题
    public class Singleton {
        private static Singleton instance = new Singleton();
    
        private Singleton() {
    
        }
    
        public static Singleton getInstance() {
            return instance;
        }
    }
    

    4.双检锁

    • 延迟加载,减少内存占用
    • 双重加锁的机制在多线程使用场景下保持性能
    • 不加volatile锁定属性的话,可能由于内存重排,导致b在c后面发生,线程不安全
      a:分配内存空间
      b:初始化对象
      c:将对象指向刚分配的内存空间
    public class Singleton {
        private volatile static Singleton instance = null;
    
        private Singleton() {
    
        }
    
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    5.静态内部类

    • 能达到和双检锁一样的功效(延迟加载+性能保证),实现更简单,在第三方库里边比较常见。
    • 也是利用classloader机制实现线程安全。但是在类其它静态方法被调用时,SingletonHolder 类没有被主动使用,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance
    public class Singleton {
        private static class SingletonHolder {
            private static final Singleton INSTANCE = new Singleton();
        }
        private Singleton (){}
    
        public static Singleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }
    

    6.枚举

    • 未延迟加载,线程安全,实现单例模式的最佳方法。它更简洁,还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化
    public enum Singleton {  
        INSTANCE;  
        public void whateverMethod() {  
    
        }  
    }
    

    三、总结

    不建议使用懒汉式,建议使用饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用静态内部类。如果涉及到反序列化创建对象时,可以尝试使用枚举方式。如果有其他特殊的需求,可以考虑使用双检锁方式。
    延迟加载:静态内部类>双检索
    非延迟加载:枚举>饿汉式

    相关文章

      网友评论

        本文标题:设计模式-单例

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