設計模式 單例模式

2022-09-09 18:39:18 字數 2708 閱讀 7126

保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點

public class singleton 

public static singleton getinatance()

}

**餓漢式是典型的空間換時間,在類裝載時進行了物件例項化,不管是否使用都先建立出來,類裝載較慢,但提取物件的速度快,餓漢式基於jvm類裝載的機制避免了多執行緒同步問題,但是沒有達到懶載入的效果, 如果從始至終從未使用過這個例項,則會造成記憶體的浪費 **

public class singleton    

public static singleton getinstance()

return instance;

} }

懶漢式例項化時機是在第一次呼叫時,實現lazy loading,第一次呼叫反應稍慢,而且多執行緒時不安全

public class singleton 

public static synchronized singleton getinstance()

return instance;

} }

這種寫法實現了執行緒安全,但是每次提取例項物件的時候,都需要進行同步,造成不必要的開銷,而且大部分時候我們用不到同步,所以不建議使用這種寫法

public class singleton    

public static singleton getinstance()

} }

return instance;

} }

雙重檢測鎖(double checked locking),有兩次對instance的判空,一次在同步塊外,次在同步塊內,因為有可能多個執行緒一起進入同步塊外的if,如果在同步塊內不進行二次檢驗的話就會生成多個例項了,兩次判空也減少了不必要的同步

注意: 這段**看起來很完美,很可惜,它是有問題。主要在於instance = new singleton()這句,這並非是乙個原子操作,事實上在 jvm 中這句話大概做了下面 3 件事情

給 instance 分配記憶體

呼叫 singleton 的建構函式來初始化成員變數

將instance物件指向分配的記憶體空間(執行完這步 instance 就為非 null 了)

但是在 jvm 的即時編譯器中存在指令重排序的優化。也就是說上面的第二步和第三步的順序是不能保證的,最終的執行順序可能是 1-2-3 也可能是 1-3-2。如果是後者,則在 3 執行完畢、2 未執行之前,被執行緒二搶占了,這時 instance 已經是非 null 了(但卻沒有初始化),所以執行緒二會直接返回 instance,然後使用,然後順理成章地報錯

我們只需要將 instance 變數宣告成 volatile 就可以了

public class singleton   

private singleton()

public static singleton getinstance()

}

**這種寫法仍然使用jvm本身機制保證了執行緒安全問題;由於 singletonholder 是私有的,除了 getinstance() 之外沒有辦法訪問它,而第一次載入singleton類時並不會初始化instance,只有第一次呼叫getinstance方法時虛擬機器載入singletonholder 並初始化instance,因此它是懶漢式的,這樣不僅能確保執行緒安全也能保證singleton類的唯一性, 同時讀取例項的時候不會進行同步,沒有效能缺陷;也不依賴 jdk 版本。 所以推薦使用靜態內部類單例模式 **

public enum singleton
可以通過easysingleton.instance來訪問例項,這比呼叫getinstance()方法簡單多了。建立列舉預設就是執行緒安全的,而且還能防止反序列化導致重新建立新的物件。但是還是很少看到有人這樣寫,不熟悉還有可讀性並不是很高

public class singletonmanager 

public static void registerservice(string key,object instance)

}public static object getservice(string key)

}

用singletonmanager 將多種的單例類統一管理,在使用時根據key獲取物件對應型別的物件。這種方式使得我們可以管理多種型別的單例,並且在使用時可以通過統一的介面進行獲取操作,降低了使用者的使用成本,也對使用者隱藏了具體實現,降低了耦合度

一般來說,單例模式有六種寫法:餓漢式 、 懶漢式 、 雙重檢測鎖 、 靜態內部 、 列舉 、 容器。

**在開發中,一般情況下直接使用餓漢式就好了,如果明確要求要懶載入(lazy loading)會傾向於使用靜態內部類,如果涉及到反序列化建立物件時會試著使用列舉的方式來實現單例 **

設計模式 單例模式

單例模式 singleton pattern 是乙個比較簡單的模式,其定義如下 ensure a class has only one instance,and provide a golbal point of acess to it.確保某乙個類只有乙個例項,而且自行例項化並且向整個系統提供這個...

設計模式 單例模式

class testsingleton static public function instance return self testsingleton private function clone public function setsinvar sinvar public function ...

設計模式 單例模式

單例模式的目的是保證類在系統中只被例項化一次,由該唯一的例項來為系統提供服務.單例模式主要用於保證服務的統一,比如獲取統一的編號服務,模仿oracle的序列生成等.但單例的使用需要謹慎,特別是在需要作負載均衡的地方,因為這種程式級的單例模式實際上只能保證在乙個應用中為單例.如果被多個應用載入,還是會...