單例模式
保證一個類隻有一個執行個體,并且提供一個通路他的全局通路點 --《設計模式:可複用面向對象軟體的基礎》84頁3.5節
在某些情況下我們需要一個類在任何情況下 隻需要同一個執行個體并且提供一個通路該執行個體的方法
單例模式又分懶漢和餓漢模式
懶漢模式:在你需要他的時候才會去建立對象,也就是你在調用通路該執行個體的方法的時候才會去建立
/**
* 單例模式 :懶漢模式
*
* @author 愛出走的眼睛
*/
public class Singleton {
private static Singleton singleton;
private Singleton() {
System.out.println("建立對象");
}
public static Singleton GetInstance() {
if (singleton==null) {
singleton=new Singleton();
return singleton;
//測試代碼
Singleton s1 = Singleton.GetInstance();
Singleton s2 = Singleton.GetInstance();
System.out.println(s1==s2);
//結果為 true
上述代碼并非嚴格,因為沒有考慮到多線程的環境下 下面我測試一下在多線程情況下出現的問題
public class Test {
public static void main(String[] args) {
Thread tA = new Thread() {
public void run() {
Singleton.GetInstance();
};
Thread tB = new Thread() {
tA.start();
tB.start();
列印結果為:
建立對象
因為在多線程的情況下 線程A可能在建立對象之前cpu時間片用完了進入就緒狀态,線程B配置設定到資源 這個時候由于線程A沒有執行完建立對象語句,此時線程B判斷依然對象為空,是以線程B也會去建立對象,這樣兩個線程都進入了if裡面 導緻單例模式失敗!
嚴格的單例模式 懶漢
* 單例模式 :嚴格的懶漢模式
//使用volatile 關鍵字 禁止指令排序
private static volatile Singleton singleton;
//這裡 鎖代碼塊比鎖方法更加高效
synchronized(Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
如果不懂volatile 和線程的話 需要自己補習一下同步鎖和volatile 關鍵字
餓漢模式: 不管你調用不調用 它都會去建立這個對象
餓漢代碼就簡單很多
public class SingletonHungry {
//注意這裡使用了final關鍵字
private static final SingletonHungry singleton=new SingletonHungry();
private SingletonHungry() {
public static SingletonHungry GetInstance(http://www.my516.com) {
應用場景
最簡單的一個小例子 windows系統中的任務管理器 無論你打開多少次任務管理器 他隻會有一個視窗
因為如果你打開兩個任務管理器視窗 且内容一樣 管理器需要去調用CPU去擷取這些資訊 這樣設計的目的是為了減少資源浪費 是以設計成單例模式,第二點 如果你打開兩個管理器發現内容不一樣 這樣更容易給使用者帶來誤解。
spring中的bean預設就是單例模式
線程池,資料庫連接配接池,日志對象這些也用到了單例模式
---------------------