• Java Singleton Implementation


    概述

    Java中单例模式的实现有多重方法, 要实现单例模式主要的问题是线程安全问题以及对Lazy Load的考虑,主要有如下几种

    1. 双重锁定懒加载单例
    2. 预加载单例
    3. 枚举单例

    双重锁定懒加载单例模式

    /**
     * 双重锁定懒加载单例实现
     *
     * @author zhenwei.liu created on 2013 13-9-23 上午10:49
     * @version 1.0.0
     */
    public class DoubleCheckedLockingSingleton {
    
        private static volatile DoubleCheckedLockingSingleton INSTANCE;
        private static Object lock = new Object();
    
        private volatile Var var;
    
        /** 阻止用户实例化单例工厂 */
        private DoubleCheckedLockingSingleton() {
            var = new Var();
        }
    
        public static DoubleCheckedLockingSingleton getInstance() {
            if (INSTANCE == null) { // 1
                synchronized (lock) {
                    if (INSTANCE == null) {
                        INSTANCE = new DoubleCheckedLockingSingleton(); //2
                    }
                }
            }
            return INSTANCE;
        }
    
        public void getVar() {
            return var;  // 3
        }
    }

    按照Happen-Before内存模型,  如果两个线程都进入了 synchronized 同步块, 则肯定能见到前一个同步块执行的内容, 但是由于出现下列情况

    1. 线程 t1 执行 1 -> 2 代码序列

    2. 线程 t2 执行 1, 然后发现INSTANCE不为空, 直接返回instance, 而并没有进入同步块, 这个时候由于没有happen-before的保证, 则 t2 在执行 3, 有可能获得的var为null(并没有看到t1在构造方法对var实例化的过程), 所以我们需要加上volatile, 这样就不会出现这个成员变量不一致的问题.

    预加载单例

    /**
     * 预加载单例实现
     *
     * @author zhenwei.liu created on 2013 13-9-23 上午10:52
     * @version 1.0.0
     */
    public class NoneLazyLoadedSingleton {
    
        /** 加载类信息时实例化单例 */
        private static NoneLazyLoadedSingleton INSTANCE = new NoneLazyLoadedSingleton();
    
        /** 阻止用户实例化单例工厂 */
        private NoneLazyLoadedSingleton() {}
    
        public static NoneLazyLoadedSingleton getInstance() {
            return INSTANCE;
        }
    
        public void action() {
            System.out.println("do something");
        }
    }

    枚举单例

    /**
     * 枚举的单例实现
     *
     * @author zhenwei.liu created on 2013 13-9-23 上午11:00
     * @version 1.0.0
     */
    public enum EnumSingleton implements Serializable {
        INSTANCE;
    
        public void action() {
            System.out.println("do something");
        }
    
        /**
         * readResolve()方法会在ObjectInputStream读取完对象准备返回前调用
         * 如果定义了readResolve()方法,则由readResolve方法指定返回对象
         *
         * @return
         */
        private Object readResolve() {
            return INSTANCE;
        }
    }

    枚举没有构造方法,它的每一个示例都是静态的单例,并且可以定义成员变量及其行为,可以说是纯天然的单例实现

    需要注意的地方是对单例反序列化的时候,需要定义readResolve()方法,否则每次反序列化readObject()方法每次都会返回一个新的示例

  • 相关阅读:
    C#拾遗(一、基本类型)
    JS正则表达式的test()方法检查汉字
    从程序员到项目经理(一)
    程序员基本素质要求
    似乎比较快
    Qt常用类
    QT 获取窗口 大小 信息
    QT 获取屏幕尺寸的法子
    Qt中 QString 和int, char等的“相互”转换
    qt 读取xml文件
  • 原文地址:https://www.cnblogs.com/zemliu/p/3334505.html
Copyright © 2020-2023  润新知