美文网首页
单例模式

单例模式

作者: 执着的逗比 | 来源:发表于2020-04-03 00:00 被阅读0次

    1)通过静态常量实现的饿汉单例模式,类一加载即初始化,没有并发问题,但是如果类初始化过大,甚至后期没有使用,会造成资源浪费。

    public class HungrySingleton {
    
        private final static HungrySingleton INSTANCE = new HungrySingleton();
    
        /*私有构造方法,防止被实例化*/
        private HungrySingleton() {}
    
        public HungrySingleton getInstance(){
            return INSTANCE;
        }
    
        public Object readResolve(){
            return INSTANCE;
        }
    
    }
    
    

    2)通过静态代码块实现的饿汉式单例,跟第一种一样的问题,类一加载即初始化,没有并发问题,但是如果类初始化过大,甚至后期没有使用,会造成资源浪费。

    public class HungrySingleton {
    
        private static HungrySingleton instance;
        
        static{
            instance = new HungrySingleton();
        }
    
        /*私有构造方法,防止被实例化*/
        private HungrySingleton() {}
    
        public HungrySingleton getInstance(){
            return INSTANCE;
        }
    
        public Object readResolve(){
            return INSTANCE;
        }
    
    }
    
    

    3)一般的懒汉式单例模式,毫无线程安全保护,如果我们把他放入多线程的环境下,肯定会出现线程安全问题。

    public class LazySingleton {
    
        private static LazySingleton instance = null;
    
        private LazySingleton() {
        }
    
        public static  LazySingleton getInstance() {
            if (instance == null) {
                instance = new LazySingleton();
            }
            return instance;
        }
    
        public Object readResolve() {
            return instance;
        }
    }
    
    

    4)通过synchronzied修饰方法的懒汉式单例模式,synchronzied关键字会把对象锁住,每次调用getInstance()时,都要把对象锁住,性能会有所下降。

    public class LazySingleton {
    
        private static LazySingleton instance = null;
    
        private LazySingleton() {
        }
    
        public static synchronized LazySingleton getInstance() {
            if (instance == null) {
                instance = new LazySingleton();
            }
            return instance;
        }
    
        public Object readResolve() {
            return instance;
        }
    }
    
    

    5)通过synchronzied修饰代码块的懒汉式单例模式,这种方式,本意是想对第四种实现方式的改进,因为前面同步方法效率太低,改为同步产生实例化的的代码块,但是这种同步并不能起到线程同步的作用。跟第3种实现方式遇到的情形一致,假如一个线程进入了if (instance== null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。

    public class LazySingleton {
    
        private static LazySingleton instance = null;
    
        private LazySingleton() {
        }
    
        public static synchronized LazySingleton getInstance() {
            if (instance == null) {
                 synchronized (LazySingleton.class) {
                       instance = new LazySingleton();
                    }
            }
            return instance;
        }
    
        public Object readResolve() {
            return instance;
        }
    }
    
    

    6)双重检查的单例模式,Double-Check概念是多线程开发中常使用到的,如代码中所示,我们进行了两次if (instance == null)检查,这样就可以保证线程安全了。这样,实例化代码只用执行一次,后面再次访问时,判断if (singleton == null),直接return实例化对象,也避免的反复进行方法同步,这种做法既可以保证线程安全,又可以延迟加载,效率较高。

    public class LazyDoubleCheckSingleton {
    
        public static LazyDoubleCheckSingleton instance = null;
    
        public LazyDoubleCheckSingleton() {
        }
    
        public static LazyDoubleCheckSingleton getInstance() {
            if (instance == null) {
                synchronized (instance) {
                    if (instance == null) {
                        instance = new LazyDoubleCheckSingleton();
                    }
                }
            }
            return instance;
        }
    
        public Object readResolve() {
            return instance;
        }
    }
    
    

    7)通过静态内部类实现的单例模式,当LazyInnerSingleton第一次被加载的时,并不会去加载SingletonInstance,只有当getInstance()方法第一次调用的时候,才会去初始化INSTANCE,第一次调用调用getInstance()方法会使虚拟机去加载SingletonInstance类,这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。

    public class LazyInnerSingleton {
        public static LazyInnerSingleton instance = null;
    
        public LazyInnerSingleton() {
        }
    
        // 定义一个内部类,用来获得实例
        private static class SingletonInstance {
            private static final LazyInnerSingleton INSTANCE = new LazyInnerSingleton();
    
        }
    
        public static LazyInnerSingleton getInstance(){
            return SingletonInstance.INSTANCE;
        }
    
        public Object readResolve() {
            return instance;
        }
    }
    
    

    8)通过枚举实现的单例模式,这借助JDK1.5中添加的枚举来实现单例模式,枚举类型是线程安全的,并且只会装载一次,不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。

    package singleton.enums;
    
    public class Singleton {
        private String name;
        private String desc;
    }
    
    package singleton.enums;
    
    public enum SingletonEnum {
        INSTANCE;
    
        private Singleton instance = null;
    
        private SingletonEnum(){
            instance = new Singleton();
        }
    
        public Singleton getInstance(){
            return instance;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:单例模式

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