單利模式的問題
其實(shí)在之前就寫了一篇關(guān)于單利設(shè)計(jì)模式中的懶漢式,也解決了懶漢式中存在的多線程安全問題盏檐,但是深入理解的時(shí)候篱昔,才發(fā)現(xiàn)問題很多
- 餓漢式的情況是怎么樣的
- 在實(shí)現(xiàn)單利后崖技,且保證線程安全的創(chuàng)建對(duì)象竭讳,序列化問題有考慮嗎?
- 下面就開始吧
先來一段餓漢式創(chuàng)建對(duì)象的方式
* @author : jzb219@gmail.com
* @description : 單利設(shè)計(jì)模式
* @date : 2018/6/25
*/
public class Singleton {
//1蛮浑、在類內(nèi)部實(shí)例化一個(gè)對(duì)象
private static Singleton singleton = new Singleton();
//2唠叛、構(gòu)造器時(shí)有,防止外部進(jìn)行new對(duì)象
private Singleton(){}
//3沮稚、對(duì)外提供一個(gè)獲取實(shí)例的靜態(tài)方法
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);
}
}
來看一下結(jié)果
說明:
在類加載的時(shí)候艺沼,通過Static靜態(tài)初始化的方式,就可以在類加載的時(shí)候創(chuàng)建對(duì)象
由于一個(gè)類只有一個(gè)類加載器蕴掏,且是在靜態(tài)初始化的時(shí)候創(chuàng)建障般,所以可以實(shí)現(xiàn)線程安全
true
而懶漢式的方式,雖然使用DCL+volatile的方式盛杰,但是在反序列一個(gè)已經(jīng)序列化過的對(duì)象的時(shí)候挽荡,就很難保證對(duì)象的唯一了
- 如果只是implements serializable是不行的,真心不明到底什么意思即供,為什么不行呢定拟,真心很難明白,又仔細(xì)看了一下序列化的實(shí)現(xiàn)逗嫡,JDK源碼中的ObjectStreamClass的getSerialFields方法
- 該方法在序列化類對(duì)象的時(shí)候getDefaultSerialFields用反射的方式來序列化
- 每次在反序列化的時(shí)候都會(huì)創(chuàng)建一個(gè)新的實(shí)例办素,由于反序列化使用的是反射技術(shù),所以相當(dāng)于對(duì)象創(chuàng)建的時(shí)候就是創(chuàng)建一個(gè)新的對(duì)象
- 如何解決呢祸穷?
/**
* 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. 很累了,準(zhǔn)備洗澡休息了
2. 穩(wěn)住情緒勺三,堅(jiān)定方向雷滚,一定能贏