設計模式之單例模式


保證系統里面的類最多只能有一個實例對象。簡單單例模式的實現:a.首先定義一個私有的變量instance來實例化類對象;b.將構造方法私有化;c.實現全局訪問點public static Singleton getInstance()方法,而由於該方法是私有的,因此變量instance也要被定義為私有的。d.如果實例需要比較復雜的實例化過程,那么就將實例化過程放在static{}

懶漢式:

public class Singleton{
private static Singleton instance = new Singleton();//定義實例變量
private Singleton(){}; //私有化構造方法
public static Singleton getInstance(){
return instance;
}
}

此實現是線程安全的,多個線程進行訪問時不會實例化多個對象,因為static屬性只會被初始化一次,缺點是無論是否用到該實例都會被初始化,無故的開銷變大。

餓漢式:

public class Singleton{
private static Singleton instance = null;
private Singleton(){};
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}

這個實現保證了只有在調用該類的時候對象才被初始化(延遲創建),但是缺點是線程不安全,當多個線程同時訪問的時候,極可能實例化出多個對象。

解決:給整個方法添加同步

(public static synchronized Singleton getInstance())

,但這樣是解決了線程的安全問題,卻大大降低了性能。確實有些不必要的同步,例如返回操作,其實真正需要同步的就是創建的時候,改進:

 s private volatile static Singleton instance = null;  

//實例對象用volatile修飾,volatile具有synchronized可見性;這樣線程就能自動發現volatile變量的最新值,這樣有一個線程實例化成功,其他線程就能立即發現。

public static Singleton getInstance(){
if(instance == null){ //如果沒有創建就進行同步創建
synchronized(Singleton.class){
if(instance == null){ //再次判斷,以防兩個線程同時經過第一道判斷,之后先后進入同步后還是能創建各自的對象的,故需再次判斷
instance = new Singleton();
}
}
}
return instance;
}

這個其實就叫(double-cheched-locking模式)

這樣還是有一個缺點就是:就是在一個線程還未完全初始化該對象時,而那個變量已經顯示為被初始化,那么其他線程可能去使用這個未被完全初始化的實例,造成系統的崩潰。不過這個在java5以上可以安全運行。

 

另外一種完美實現的實現既線程安全又延遲加載的模式(Initialization on demand holder)使用靜態內部類  示例:

Public class Singleton{
Private Singleton(){};
Public static class Singleton1{
Private static final Singleton instance = new Singleton();
}
Public static Singleton getInstance(){
Return Singleton1.instance;
}
}

這樣就能保證在第一次調用getInstance()方法時,才會去初始化instance實例,而且該實例被定義為static,只會被初始化一次。

接下去還有一個問題就是單例化類的序列化問題:如果單例類實現了serializable接口,這是要特別注意以為在默認情況下,每次反序列化時總會創建一個新的對象,注意系統就會出現多個對象了。解決方法:根據序列化可知:每次反序列化完成前都會去調用readResolve()方法,那就在該方法中,將用原對象取代新創建出來的對象。在是在該實現了序列化的類中再定義一個方法:

 Public Singleton readResolve(){

    sReturn instance;                   // instance是唯一的實例對象

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM