(1)問題分析:
主要考察懶漢和餓漢模式在建立時的差別以及分别在什麼情況下使用懶漢模式,什麼情況下使用餓漢模式。
懶漢模式:在類加載的時候不被初始化。
餓漢模式:在類加載時就完成了初始化,但是加載比較慢,擷取對象比較快。
餓漢模式是線程安全的,在類建立好一個靜态對象提供給系統使用,懶漢模式在建立對象時不加上synchronized,會導緻對象的通路不是線程安全的。
(2)核心答案講解:
餓漢式:
public class Singleton{
private static Singleton singleton = new Singleton ();
private Singleton (){}
public static Singleton getInstance(){return singletion;}
}
懶漢式:
public class Singleton{
private static Singleton singleton = null;
public static synchronized synchronized getInstance(){
if(singleton==null){
singleton = new Singleton();
}
return singleton;
}
}
餓漢式是線程安全的,在類建立的同時就已經建立好一個靜态的對象供系統使用,以後不在改變
懶漢式如果在建立執行個體對象時不加上synchronized則會導緻對對象的通路不是線程安全的。
從實作方式來講他們最大的差別就是懶漢式是延時加載,是在需要的時候才建立對象,而餓漢式在虛拟機啟動的時候就會建立。
(3)問題擴充
懶漢式不會預先建立對象,隻在第一次調用時才建立對象,但是多線程并發執行的時候就很容易出現安全隐患,比如說第一個線程在判斷newInstance == null時,還沒有new出執行個體時,第二個線程也進來,判斷的newInstance也是null,然後也會new出執行個體,這就不符合單例模式了, 是以需要加鎖。使用synchronized關鍵字加鎖能解決安全問題,但是加鎖同時會出現一個問題,那就是每次都需要判斷鎖,這樣性能就會降低,是以為了提高性能,我們應該盡量減少鎖判斷的次數,加上雙重判斷。
//靜态工廠方法、單鎖
public synchronized static SingletonTest2 getInstance1(){
if (single2==null) {
single2 = new SingletonTest2();
}
return single2;
}
//靜态工廠方法、雙重鎖
public static SingletonTest2 getInstance2(){
if (single2==null) {
synchronized (SingletonTest2.class) {
if (single2==null) {
single2 = new SingletonTest2();
}
}
}
return single2;
}
(4)結合項目中的使用
懶漢式的特點是延遲加載,比如配置檔案,采用懶漢式的方法。
猜你喜歡