創(chuàng)建一個(gè)單例有哪幾種方式:
懶漢式,延遲加載,使用這個(gè)對象的時(shí)候才去創(chuàng)建蔬将,優(yōu)點(diǎn)是節(jié)省資源爷速,缺點(diǎn)是需要考慮線程安全。
餓漢式娃胆,立即加載遍希,使用類的時(shí)候已經(jīng)將對象創(chuàng)建完畢,優(yōu)點(diǎn)是線程安全里烦,缺點(diǎn)是浪費(fèi)資源凿蒜。
靜態(tài)內(nèi)部類方式實(shí)現(xiàn)單例
public class StaticSingleton{
private StaticSingleton(){}
private static class SingletonHolder{
private static StaticSingleton singleton = new StaticSingleton();
}
public StaticSingleton getInstance(){
return SingletonHolder.singleton;
}
}
單例模式序列化與反序列化的問題
反序列化時(shí),從內(nèi)存讀出而組裝的對象破壞了單例的規(guī)則. 單例是要求一個(gè)JVM中只有一個(gè)類對象的, 而現(xiàn)在通過反序列化,一個(gè)新的對象克隆了出來.
如下例所示:
public final class MySingleton implements Serializable {
private MySingleton() { }
private static final MySingleton INSTANCE = new MySingleton();
public static MySingleton getInstance() { return INSTANCE; }
}
當(dāng)把 MySingleton對象(通過getInstance方法獲得的那個(gè)單例對象)序列化后再從內(nèi)存中讀出時(shí), 就有一個(gè)全新但跟原來一樣的MySingleton對象存在了. 那怎么來維護(hù)單例模式呢?這就要用到readResolve方法了. 如下所示:
public final class MySingleton implements Serializable{
private MySingleton() { }
private static final MySingleton INSTANCE = new MySingleton();
public static MySingleton getInstance() { return INSTANCE; }
private Object readResolve() throws ObjectStreamException {
// instead of the object we're on,
// return the class variable INSTANCE
return INSTANCE;
}
}
這樣當(dāng)JVM從內(nèi)存中反序列化地"組裝"一個(gè)新對象時(shí),就會(huì)自動(dòng)調(diào)用這個(gè) readResolve方法來返回我們指定好的對象了, 單例規(guī)則也就得到了保證.