单利模式的问题
其实在之前就写了一篇关于单利设计模式中的懒汉式,也解决了懒汉式中存在的多线程安全问题,但是深入理解的时候,才发现问题很多
- 饿汉式的情况是怎么样的
- 在实现单利后,且保证线程安全的创建对象,序列化问题有考虑吗?
- 下面就开始吧
先来一段饿汉式创建对象的方式
* @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的方式,但是在反序列一个已经序列化过的对象的时候,就很难保证对象的唯一了
- 如果只是implements serializable是不行的,真心不明到底什么意思,为什么不行呢,真心很难明白,又仔细看了一下序列化的实现,JDK源码中的ObjectStreamClass的getSerialFields方法
- 该方法在序列化类对象的时候getDefaultSerialFields用反射的方式来序列化
- 每次在反序列化的时候都会创建一个新的实例,由于反序列化使用的是反射技术,所以相当于对象创建的时候就是创建一个新的对象
- 如何解决呢?
/**
* 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. 稳住情绪,坚定方向,一定能赢