單例模式使用總結
阿新 • • 發佈:2019-01-23
前言
記錄單例模式的多種使用方式,以及自己的理解
餓漢模式
public class HungrySingleMode {
private static HungrySingleMode mInstance=new HungrySingleMode();
private HungrySingleMode(){}
public static HungrySingleMode getInstance(){
return mInstance;
}
}
個人理解
類載入的時候把靜態的變數已經載入到記憶體裡了,使用的時候直接獲取不用再建立例項物件,執行時稍微快一些。如果沒有被使用,則有點浪費記憶體。因為在類載入的時候已經建立了唯一的例項,所以在多執行緒執行的時候不會出現同步的問題。
懶漢模式(執行緒不安全)
public class LazySingleMode {
private static LazySingleMode mInstance=null;
private LazySingleMode(){}
public static LazySingleMode getInstance(){
if(mInstance==null){
mInstance=new LazySingleMode();
}
return mInstance;
}
}
個人理解
在第一次呼叫的時候才會建立例項,這就導致執行的時候會稍微慢一些,但是又保證了不會浪費記憶體。在同步方面如果兩個執行緒同時呼叫這個方法,由於沒有同步鎖的控制,會導致建立多個例項,會出現同步問題。
懶漢模式(執行緒安全)
public class LazySingleSafeMode {
private static LazySingleSafeMode mInstance;
private LazySingleSafeMode(){}
public static synchronized LazySingleSafeMode getInstance(){
if (mInstance==null){
mInstance=new LazySingleSafeMode();
}
return mInstance;
}
}
個人理解
在呼叫的方法上加上同步鎖解決同步問題,但是每次呼叫都要去判斷同步的問題,增加了開銷。
雙重檢查模式(DCL)
public class DLCSingleMode {
private volatile static DLCSingleMode mInstance;
private DLCSingleMode(){}
public static DLCSingleMode getInstance(){
if (mInstance==null){
synchronized (DLCSingleMode.class){
if(mInstance==null){
mInstance=new DLCSingleMode();
}
}
}
return mInstance;
}
}
個人理解
首先,靜態變數用volatitle關鍵字申明,保證了原子性(有待深入理解)。
其次,在呼叫方法裡面進行了兩次判空,第二次判空進行程式碼塊的同步鎖定,保證同步問題。第一次判空可以避免多次同步的呼叫,既保證同步也避免了多餘的同步開銷浪費。
最後,在某些情況下也會存在失效的問題,具體情況待深入理解。
靜態內部類
public class StaticInnerSingleMode {
private StaticInnerSingleMode(){}
public static StaticInnerSingleMode getInstance(){
return SingletonHolder.instance;
}
private static class SingletonHolder{
private static final StaticInnerSingleMode instance=new StaticInnerSingleMode();
}
}
個人理解
在類載入的時候,不會初始化instance例項,只有在第一次呼叫的時候才會建立例項,同時也能保證執行緒安全。
列舉單例
public enum EnumSingleMode {
INSTANCE;
public void doSomeThing(){}
}
個人理解
預設列舉例項的建立時執行緒安全的,並且在任何情況下都是單列。–《Android 進階之光》 劉望舒
總結
經過看書學習使用對單例模式有更深刻的認識,當然還有一些不理解之處,需要繼續研究。