面試題2:實現Singleton模式
阿新 • • 發佈:2018-12-13
題目:設計一個類,我們只能生成該類的一個例項
思路:
1)不能開發類的構造方法,不然誰都可以通過構造方法搭建,所以將構造方法私有化;
2)建立一個靜態例項,根據需要建立一個例項,但也要將該例項私有化,防止外部獲取該例項時例項還未建立;
3)建立一個方法獲取2中的靜態例項。
解法一:(只適合單執行緒)
public class Singleton { private Singleton(){ } private static Singleton instance=null; public static Singleton Instance(){ if(instance==null){ instance=new Singleton(); } return instance; } }
缺點:只適合單執行緒環境,多執行緒下,如果兩個執行緒同時判斷instance是否為空,且instance確實沒有建立,那兩個執行緒就會同時建立一個例項,就不符合題目要求了
解法二:(適合多執行緒,但效率低)
public class Singleton { private Singleton(){ } private static Singleton instance=null; public static Singleton Instance(){ synchronized (Singleton.class) { if(instance==null){ instance=new Singleton(); } } return instance; } }
缺點:每次獲取例項時都要等待獲取物件鎖和加同步鎖,效率慢
解法三:(適合多執行緒,效率也高)
public class Singleton { private Singleton(){ } private static Singleton instance=null; public static Singleton Instance(){ if(instance==null){ synchronized (Singleton.class) { if(instance==null){ instance=new Singleton(); } } } return instance; } }
分析:用兩個if判斷來提高效率,這樣當instance被建立之後,就不用被加鎖解鎖了,不過程式碼複雜,容易出錯。
解法四:(強烈推薦)
public class Singleton {
private Singleton(){
}
private static Singleton instance=new Singleton();
public static Singleton Instance(){
return instance;
}
}
分析:直接在初始化靜態變數時就建立例項,這樣只要類被呼叫的時候就會建立一個例項,如果在類中建立一個靜態方法,呼叫該靜態方法,即使此時不會使用該例項,也會建立該例項,因為靜態變數和靜態程式碼塊只要類被呼叫就會被初始化;當然,如果Singleton.class.getName()不會初始化靜態變數和靜態程式碼塊,因為JVM在載入類的過程中分為五個階段:載入、驗證、準備、解析、初始化,靜態變數和靜態程式碼塊的初始化發生在初始化階段,類.class發生在載入階段。
解法五:(強烈推薦)
public class Singleton {
private Singleton(){
}
public static Singleton Instance(){
return InstanceFactory.instance;
}
static class InstanceFactory{
private static final Singleton instance=new Singleton();
};
}
分析:在需要的時候再建立例項,因為靜態內部類只有在本身被外部類呼叫時才會初始化,就算建立一個外部類的例項,執行外部類的方法,只要沒有執行到內部類的程式碼,靜態內部類就不會被初始化。
今天努力一點點,以後輕鬆一點點。