單例模式:指乙個類只有乙個例項,且該類只能由自己自行建立這個例項的一種模式,對外提供乙個獲取例項的方法,不需要例項化該類的物件。
單例模式有三個特點:
單例類只有乙個物件
該單例物件必須由單例類自行建立
單例類對外提供乙個訪問該單例的全域性訪問點
優點
單例模式可以保證記憶體裡只有乙個例項,減少了記憶體的開銷
可以避免對資源的多重占用
單例模式設定全域性訪問點,可以優化和共享資源的訪問
缺點
不適用於經常變化的物件,入同一型別的物件經常在不同的場景下變化,容易引起資料錯誤
單例模式一般沒有抽象層,擴充套件困難,違背了開閉原則
單例模式所有的**都寫在了乙個類中,可能會違背單一職責原則
注:
實現單例模式需要先將構造方法私有化,這裡為了減少**量,就省略了私有化構造方法的**
懶漢式,顧名思義,非常的懶,只有在用到這個物件的時候才會去初始化
優點:
節省記憶體,如果物件一直不被使用,則不會初始化
缺點:
執行緒不安全
public
class
singleton
return singleton;
}}
普通懶漢式是執行緒不安全,例如有多個執行緒同步獲取例項,那麼同時進行物件非空判斷,在同一時間都判斷物件為空,然後進行建立,則會建立出多個物件,這裡使用同步鎖來保證執行緒安全
優點
執行緒安全
缺點
效率十分低下,因為對於物件的非空判斷只需要在初始化時判斷就可以,但是同步的加入,使得每次獲取物件都要先拿到鎖再判斷非空,獲取鎖的過程是非常浪費資源的,所以使用同步鎖效率會很低。
public
class
singleton
return singleton;
}}
雙重鎖,就是將同步鎖,下移至物件為空時進行初始化,這樣,就是所有的執行緒同時判斷物件為空,初始化物件的執行緒也只有拿到鎖的哪乙個。
public
class
singleton}}
return singleton;
}}
但是這段**,在jdk1.5之前,是有乙個隱患的,標記為label哪一行,理想的執行過程應該是這樣的
分配記憶體空間
初始化物件
將物件指向剛才分配的記憶體空間
但是,有些編譯器為了效能問題,可能會將第二步與第三步進行重排序,順序就變成了
分配記憶體空間
將物件指向剛才分配的記憶體空間
初始化物件
這樣一來,如果多個執行緒(a、b、c)同時進來,a執行緒正在初始化物件,正好執行完了分配記憶體空間,此時物件已經不為空了,然後b、c執行緒進來獲取物件,判斷物件不為空,獲取物件,但是物件並未初始化完成,那麼這個時候獲取到的就是乙個錯誤的物件。
解決方案
使用volatile修飾符修飾物件,讓編譯器不對這個物件進行重排序。使用了volatile關鍵字後,重排序被禁止,所有的寫(write)操作都將發生在讀(read)操作之前。
public
class
singleton}}
return singleton;
}}
這個問題在jdk1.5之後已經被sun公司解決了,所以jdk1.5之後不需要volatile修飾符。
餓漢式,顧名思義,就是很飢餓的意思,不管這個例項能不能用得上,我都在程式啟動時,就初始化物件
優點
不會出現執行緒不安全的問題,初始化在獲取物件之前就已經完成了,所有的執行緒拿到的都是同乙個物件
缺點
因為物件不一定能用上,容易造成記憶體空間的浪費
public
class
singleton
}
靜態內部類就很好的解決了執行緒不安全和記憶體空間浪費的問題,這個方案是將物件儲存在內部的乙個靜態類中,只有在需要用到這個物件時,才會進行初始化(靜態內部類在程式啟動時不會進行載入,只有在使用到外部類時才會被載入,具體細節請參考jvm虛擬機器相關資料)
public
class
singleton
private
static
class
singletoninstance
}
以上五種實現單例模式的方式,都存在反射攻擊和序列化以及反序列化之後出現多個例項的問題,但是列舉不會,因為列舉不能被例項化,自始至終都是只有乙個型別,不管是序列化和反序列化,還是通過反射構建例項,都不會得到兩個物件。
public
enum singleton
}
呼叫方式:
public
class
main
}
設計模式 單例模式
單例模式 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的序列生成等.但單例的使用需要謹慎,特別是在需要作負載均衡的地方,因為這種程式級的單例模式實際上只能保證在乙個應用中為單例.如果被多個應用載入,還是會...