單例模式,屬於建立型別的一種常用的軟體設計模式。通過單例模式的方法建立的類在當前程序中只有乙個例項(根據需要,也有可能乙個執行緒中屬於單例,如:僅執行緒上下文內使用同乙個例項)懶漢單例模式(多執行緒不安全)
餓漢單例模式(多執行緒安全)
靜態內部類單例模式(多執行緒安全)
雙檢索單例模式(dcl)(多執行緒安全)
public class singleinstance
private static singleinstance singleinstance = null;
public static singleinstance getinstance()
return singleinstance;
}}
優點:實現了懶載入
缺點:執行緒不安全
public class singleinstance
private static singleinstance singleinstance = new singleinstance();
public static singleinstance getinstance()
}
優點:多執行緒安全
缺點:沒有實現懶載入,可能會造成空間浪費的問題
public class singleinstance
public static singleinstance getinstance()
private static class singleinstanceholder
}
優點:延遲載入,多執行緒安全
public class singleinstance
private volatile static singleinstance singleinstance = null;
public static singleinstance getinstance() }}
return singleinstance;
}}
優點:延遲載入、多執行緒安全
問題解答
1、 dcl為什麼要兩次檢查singleinstance是否等於null呢?
解答:主要是為了避免多執行緒問題。首先,第一次判斷是否為null,如果不為null的話,可以直接把物件返回,不需要再獲取鎖,提高了效率。第二次再判斷是否為null的原因是:假如執行緒a持有鎖,在執行了同步**塊中的內容,但是還沒有對singleinstance進行建立;所以執行緒b已經判斷到singleinstance為null,並且已經執行到synchronized (singleinstance.class)
的地方然後阻塞。等到執行緒a執行完同步**並且釋放鎖之後,執行緒b就能開始執行同步**塊裡面的內容了,如果不再加一次判斷if(singleinstance==null)
,執行緒b會繼續new乙個物件,這樣就導致了這個就不是單例模式了。
2、dcl中singleinstance singleinstance = null;
為什麼需要加volatile關鍵字?在堆中分配物件記憶體
填充物件必要資訊+具體資料初始化+末位填充
將引用指向這個物件的堆內位址
這幾條系統指令重排序之後的順序很可能會變成1、3、2。假設執行緒a按照1、3、2順序開始執行,執行到第3步「將引用指向這個物件的堆內位址」,但是第2步「填充物件必要資訊+具體資料初始化+末位填充」卻還沒有執行,這個時候執行緒b讀取到singleinstance!=null,並開始使用singleinstance,這個時候的singleinstance雖然不為null,但是還是不可用的,所以會爆出錯誤。volatile就是為了解決這個重排序問題的,加了volatile後,1、2、3這3個步驟就會嚴格按照順序執行。
單例模式詳解
單例模式的意思就是只有乙個例項。單例模式確保某乙個類只有乙個例項,而且自行例項化並向整個系統提供這個例項。這個類稱為單例類。1.單例模式的要點 顯然單例模式的要點有三個 一是某個類只能有乙個例項 二是它必須自行建立這個例項 三是它必須自行向整個系統提供這個例項。2.單例模式的優點 1.例項控制 si...
單例模式詳解
單例模式是設計模式中比較常用的,今天我要詳細的了解一下,並且進行一些比較 public class singleton public static singleton getinstance catch interruptedexception e 單例模式的精髓就在這,類的內部可以new inst...
單例模式 詳解
保證乙個類僅有乙個例項,並且提供乙個訪問它的全域性訪問點 在該例項不存在的情況下,可以通過乙個方法建立乙個類來實現建立類的新例項 如果例項已經存在,它會簡單返回該物件的引用 建立型模式 var singleton function return var singlea singleton.getin...