一:為什麼使用
物件頻繁建立、銷毀對系統效能和記憶體來說不是乙個好事情,特別是及其消耗資源的大物件
或是物件例項化需要進行i/o操作
。使用單例模式在記憶體中確保物件唯一
,可以很好解決上述問題
二:餓漢式單例
public
class
singleton
private
static singleton sf =
newsingleton()
;public
static singleton getinstance()
}
餓漢式特點:
私有建構函式阻止new例項化物件操作確保物件唯一
提供靜態方法返回物件
餓漢式問題:
靜態屬性sf會跟隨類載入完成物件例項初始化,但是如果這個物件暫時是不需要的,是否可以延時載入即使用再初始化
三:懶漢式單例
public
class
singleton
private
static singleton sf = null;
public
static singleton getinstance()
}
懶漢式特點:
通過在方法中判斷、建立物件的方式實現了延時載入的目標
懶漢式問題:
if條件判斷的使用導致併發場景下物件不唯一情況產生,即執行緒a通過判定在初始化之前執行緒b獲得資源完成初始化,這時候a再獲取資源進行初始化操作
四:雙重鎖校驗
直接在getinstance()上加synchronized關鍵字確實可以解決執行緒安全問題,但是鎖是及其消耗資源的,為了效能最優可以減少鎖資源爭奪從而提出雙重鎖校驗
public
class
singleton
private
static
volatile singleton sf = null;
private
static
final object o =
newobject()
;public
static singleton getinstance()
}return sf;
}}
務必注意sf物件使用關鍵字volatile
修飾保證執行緒間資料透明,執行緒可以及時獲取到sf物件的變化資訊
五:內部類實現
雙重鎖校驗在一定程度上優化了併發執行緒對於鎖資源的爭奪,但是還是無法完全避免。利用內部類實現則可以從根上改變使用鎖解決執行緒安全問題
public
class
singleton
private
static
class
innerclass
public
static singleton getinstance()
}
六:序列化、反射安全
上面四個單例模式方案逐步遞進解決有關延遲載入與執行緒安全等,但是都共同存在反序列化破壞單例規則即反序列化產生不唯一物件
的問題
public
class
singleton
implements
serializable
private
static singleton s =
newsingleton()
;public
static singleton getinstance()
public
static
void
write()
throws ioexception
public
static singleton get()
throws ioexception, classnotfoundexception
public
static
void
main
(string[
] args)
throws ioexception, classnotfoundexception
}
解決序列化帶來的物件不唯一問題比較簡單粗暴,如下所示宣告方法readresolve()
即可:
private object readresolve()
反射對單例模式的破壞同樣很直接,針對反射問題可以對建構函式進行如下處理。對單例模式的類使用反射本身就是在犯罪,雖然如下處理可以防止,但是要鐵了心修改flag的值這也是無法防範
private
static
boolean flag =
true
;private
singleton()
設計模式 單例模式
單例模式 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的序列生成等.但單例的使用需要謹慎,特別是在需要作負載均衡的地方,因為這種程式級的單例模式實際上只能保證在乙個應用中為單例.如果被多個應用載入,還是會...