美文网首页
单利设计模式(二)

单利设计模式(二)

作者: T_log | 来源:发表于2018-06-25 23:26 被阅读13次

    单利模式的问题

    其实在之前就写了一篇关于单利设计模式中的懒汉式,也解决了懒汉式中存在的多线程安全问题,但是深入理解的时候,才发现问题很多

    1. 饿汉式的情况是怎么样的
    2. 在实现单利后,且保证线程安全的创建对象,序列化问题有考虑吗?
    3. 下面就开始吧

    先来一段饿汉式创建对象的方式

     * @author : jzb219@gmail.com
     * @description : 单利设计模式
     * @date : 2018/6/25
     */
    public class Singleton {
    
        //1、在类内部实例化一个对象
        private static Singleton singleton = new Singleton();
    
        //2、构造器时有,防止外部进行new对象
        private Singleton(){}
    
        //3、对外提供一个获取实例的静态方法
        public static Singleton getInstance(){
            return singleton;
        }
    
         public static void main(String[] args) {
            Singleton instance = Singleton.getInstance();
            Singleton instance2 = Singleton.getInstance();
            System.out.println(instance == instance2);
        }
    }
    

    来看一下结果
    说明:
    在类加载的时候,通过Static静态初始化的方式,就可以在类加载的时候创建对象
    由于一个类只有一个类加载器,且是在静态初始化的时候创建,所以可以实现线程安全

     true
    

    而懒汉式的方式,虽然使用DCL+volatile的方式,但是在反序列一个已经序列化过的对象的时候,就很难保证对象的唯一了

    1. 如果只是implements serializable是不行的,真心不明到底什么意思,为什么不行呢,真心很难明白,又仔细看了一下序列化的实现,JDK源码中的ObjectStreamClass的getSerialFields方法
    2. 该方法在序列化类对象的时候getDefaultSerialFields用反射的方式来序列化
    3. 每次在反序列化的时候都会创建一个新的实例,由于反序列化使用的是反射技术,所以相当于对象创建的时候就是创建一个新的对象
    4. 如何解决呢?
    /**
         * Returns ObjectStreamField array describing the serializable fields of
         * the given class.  Serializable fields backed by an actual field of the
         * class are represented by ObjectStreamFields with corresponding non-null
         * Field objects.  Throws InvalidClassException if the (explicitly
         * declared) serializable fields are invalid.
         */
        private static ObjectStreamField[] getSerialFields(Class<?> cl)
            throws InvalidClassException
        {
            ObjectStreamField[] fields;
            if (Serializable.class.isAssignableFrom(cl) &&
                !Externalizable.class.isAssignableFrom(cl) &&
                !Proxy.isProxyClass(cl) &&
                !cl.isInterface())
            {
                if ((fields = getDeclaredSerialFields(cl)) == null) {
                    fields = getDefaultSerialFields(cl);
                }
                Arrays.sort(fields);
            } else {
                fields = NO_FIELDS;
            }
            return fields;
        }
    

    看下解决

    使用final防止序列化
    参考(http://www.hollischuang.com/archives/1373)

    1. 很累了,准备洗澡休息了
    2. 稳住情绪,坚定方向,一定能赢
    

    相关文章

      网友评论

          本文标题:单利设计模式(二)

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