单例模式的最佳实现

    第一种:饿汉式单利模式,在装载该单例类的时候就会创建类实例
    public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton() {}
        public static Singleton getInstance() {
            return instance;
        }
    }
    第二种:懒汉单例模式:(延迟加载思想)这一思想的核心在于直到需要使用某些资源或数据时再去加载该资源或获取该数据,这样可以尽可能地节省使用前的内存空间,一般推荐的单例模式都是懒汉模式。
    public class Singleton {
    private static Singleton instance = null;
    private Singleton() {}
        public static Singleton getInstance() {
            //  如果instance未被初始化,则初始化该类实例
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    第三种:线程安全的懒汉单例模式:
    public class Singleton {
    private static Singleton instance = null;
    private Singleton() {}
        public static synchronized Singleton getInstance() {
            //  如果instance未被初始化,则初始化该类实例
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    第四种:线程安全的懒汉单利模式:(双重检查加锁机制):在程序每次调用getInstance()方法时先不进行同步,而是在进入该方法后再去检查类实例是否存在,若不存在则进入接下来的同步代码块;进入同步代码块后将再次检查类实例是否存在,若不存在则创建一个新的实例,这样一来,就只需要在类实例初始化时进行一次同步判断即可,而非每次调用getInstance()方法时都进行同步判断,大大节省了时间。
    public class Singleton {
    /**
     * 装载时不创建类实例,但需要利用一个类变量去保存后续创建的类实例
     * 添加volatile关键词使其不会被本地线程缓存,保证线程能正确处理
     * 添加static关键词使得该变量能在getInstance()静态方法中使用
     */
    private volatile static Singleton instance = null;
    private Singleton() {}
        public static Singleton getInstance() {
            //  第一重检查:如果instance未被初始化,则进入同步代码块
            if (instance == null) {
                //  同步代码块,保证线程安全
                synchronized (Singleton.class) {
                    //  第二重检查:如果instance未被初始化,则初始化该类实例
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    第五种:既然有单例模式,会不会有双例模式、三例模式等
    public class Singleton {
        //  可创建的最大类实例数,这里以“双例模式”为例
        private static final int MAX = 2;
        //  类实例缓存KEY值
        private static final String KEY = "CACHE";
        //  当前正在使用的实例序号
        private static int index = 1;
        //  类实例缓存容器
        private static Map<String, Singleton> map = new HashMap<>();
        /**
        * 私有化构造方法,使外部无法通过构造方法构造除instance外的类实例
        * 从而达到单例模式控制类实例数目的目的
        */
        private Singleton() {}
        /**
        * 类实例的全局访问方法
        * 添加static关键词使得外部可以通过类名直接调用该方法获取类实例
        * @return 单例类实例
        */
        public static Singleton getInstance() {
            //  尝试从缓存容器中获取第index个类实例
            String key = KEY + index;
            Singleton instance = map.get(key);
            //  未能获取类实例,则初始化该实例,并将其缓存至容器相应index中
            if (instance == null) {
                instance = new Singleton();
                map.put(key, instance);
            }
            //  这里以最基本的顺序调用为例,其他复杂调度方式不加讨论,具体调用方式如下
            //  index++,以在下一次调用中获取下一个类实例,当达到类实例数上限时,重新获取第一个类实例
            if ((++index) > MAX) {
                index = 1;
            }
            return instance;
        }
    }
    第六种:单例模式的最佳实现:
    public class Singleton {
        /**
         * 类级内部类,用于缓存类实例
         * 该类将在被调用时才会被装载,从而实现了延迟加载
         * 同时由于instance采用静态初始化的方式,因此JVM能保证其线程安全性
         */
        private static class Instance {
            private static Singleton instance = new Singleton();
        }
        /**
         * 私有化构造方法,使外部无法通过构造方法构造除instance外的类实例
         * 从而达到单例模式控制类实例数目的目的
         */
        private Singleton() {}
        /**
         * 类实例的全局访问方法
         * 添加static关键词使得外部可以通过类名直接调用该方法获取类实例
         * @return 单例类实例
         */
        public static Singleton getInstance() {
            return Instance.instance;
        }
    }

猜你喜欢

转载自blog.csdn.net/u011635492/article/details/80150464