单利设计模式(二)

2018-06-25  本文已影响13人  T_log

单利模式的问题

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

  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. 稳住情绪,坚定方向,一定能赢
上一篇下一篇

猜你喜欢

热点阅读