設計模式之單例模式
什麼是單例設計模式?
單例模式,是一種常用的軟體設計模式。在它的核心結構中隻包含一個被稱為單例的特殊類。通過單例模式可以保證系統中,應用該模式的類一個類隻有一個執行個體。即一個類隻有一個對象執行個體.
類結構圖

具體實作
需要:
(1)将構造方法私有化,使其不能在類的外部通過new關鍵字執行個體化該類對象。
(2)在該類内部産生一個唯一的執行個體化對象,并且将其封裝為private static類型。
(3)定義一個靜态方法傳回這個唯一對象。
實作一:立即加載 / “餓漢模式”
立即加載就是使用類的時候已經将對象建立完畢(不管以後會不會使用到該執行個體化對象,先建立了再說。很着急的樣子,故又被稱為“餓漢模式”),常見的實作辦法就是直接new執行個體化。
public class Singleton {
// 将自身執行個體化對象設定為一個屬性,并用static、final修飾
private static final Singleton instance = new Singleton();
// 構造方法私有化
private Singleton() {}
// 靜态方法傳回該執行個體
public static Singleton getInstance() {
return instance;
}
}
“餓漢模式”的優缺點:
優點:實作起來簡單,沒有多線程同步問題。
缺點:當類SingletonTest被加載的時候,會初始化static的instance,靜态變量被建立并配置設定記憶體空間,從這以後,這個static的instance對象便一直占着這段記憶體(即便你還沒有用到這個執行個體),當類被解除安裝時,靜态變量被摧毀,并釋放所占有的記憶體,是以在某些特定條件下會耗費記憶體。
實作二:延遲加載 / “懶漢模式”
延遲加載就是調用get()方法時執行個體才被建立(先不急着執行個體化出對象,等要用的時候才給你建立出來。不着急,故又稱為“懶漢模式”),常見的實作方法就是在get方法中進行new執行個體化。
public class Singleton {
// 将自身執行個體化對象設定為一個屬性,并用static修飾
private static Singleton instance;
// 構造方法私有化
private Singleton() {}
// 靜态方法傳回該執行個體
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
“懶漢模式”的優缺點:
優點:實作起來比較簡單,當類SingletonTest被加載的時候,靜态變量static的instance未被建立并配置設定記憶體空間,當getInstance方法第一次被調用時,初始化instance變量,并配置設定記憶體,是以在某些特定條件下會節約了記憶體。
缺點:在多線程環境中,這種實作方法是完全錯誤的,根本不能保證單例的狀态。
實作三:線程安全的“懶漢模式”
public class Singleton {
// 将自身執行個體化對象設定為一個屬性,并用static修飾
private static Singleton instance;
// 構造方法私有化
private Singleton() {}
// 靜态方法傳回該執行個體,加synchronized關鍵字實作同步
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
優點:在多線程情形下,保證了“懶漢模式”的線程安全。
缺點:衆所周知在多線程情形下,synchronized方法通常效率低,顯然這不是最佳的實作方案。
補充:
synchronized關鍵字的作用域有二種:
1)是某個對象執行個體内,synchronized aMethod(){} 可以防止多個線程同時 通路這個對象的synchronized方法 (如果一個對象有多個synchronized方法,隻要一個線程通路了其中的一個synchronized方法,其它線程不能同時通路這個對象中任何一個synchronized方法 )。這時,不同的對象執行個體的 synchronized方法是不相幹擾的。也就是說,其它線程照樣可以同時通路相同類的另一個對象執行個體中的synchronized方法;
總的來說,這種情況,鎖就是這個方法所在的對象
2)是某個類的範圍,synchronized static aStaticMethod{} 防止多個線程同時通路這個類中的synchronized static 方法 。它可以對類的所有對象執行個體起作用。此時鎖就是這個class
實作四:DCL雙檢查鎖機制(DCL:double checked locking)
public class Singleton {
// 将自身執行個體化對象設定為一個屬性,并用static修飾
private static Singleton instance;
// 構造方法私有化
private Singleton() {}
// 靜态方法傳回該執行個體
public static Singleton getInstance() {
// 第一次檢查instance是否被執行個體化出來,如果沒有進入if塊
if(instance == null)
{
synchronized (Singleton.class)
{
// 某個線程取得了類鎖,執行個體化對象前第二次檢查instance是否已經被執行個體化出來,如果沒有,才最終執行個體出對象
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
方法四算是單例模式的最佳實作方式。記憶體占用率高,效率高,線程安全,多線程操作原子性。
補充:
除了方法前用synchronized關鍵字,synchronized關鍵字還可以用于方法中的某個區塊中,表示隻對這個區塊的資源實行互斥通路。
用法是: synchronized(this){/區塊/},鎖就是這個方法所在的對象 ;
原文:https://www.cnblogs.com/binaway/p/8889184.html