單例模式:確保某個類只有乙個例項,並且只能自行例項化並且向系統提供這個示例。單例模式有幾個特點:
單例模式在很多場景都可以使用到,比如執行緒池、快取、日誌物件、印表機或者顯示卡驅動的物件等等,這些場景下,如果有多個例項的話,可能會導致程式的行為異常、資源使用過量等問題的出現。因此,學習單例模式是很有必要的。
在單例模式中,主要有兩種方式實現單例模式:
1. 懶漢式
懶漢:顧名思義,很懶!所以這個例項是在第一次呼叫的時候才會進行例項化。
//懶漢式單例類.在第一次呼叫的時候例項化自己
public
class
singleton
private
static singleton single=null;
//靜態工廠方法
public
static singleton getinstance()
return single;
} }
從**中可以看出,實現懶漢式單例類有兩個步驟:
將構造方法私有化,並將物件設定為靜態私有提供乙個靜態方法供外部程式呼叫獲取例項。
實現了以上兩個步驟之後,當外部程式第乙個訪問這個單例類的時候,singleton將會進行例項化並返回。
那麼,考慮乙個問題:多執行緒下會發生什麼問題?
我們可以把自己當做jvm來執行一下這個程式:
這是執行權交回執行緒一,在停掉的那個地方繼續往下執行,例項化 singleton 物件,再返回。
這樣,導致返回了兩個不同的物件,破壞了單例模式的原則:單例類只能有乙個例項
那麼,怎麼解決呢?
我們有兩種方法解決這個問題:
在getinstance方法上加同步
public
static
synchronized singleton getinstance()
return single;
}
雙重檢查加鎖
private
volatile
static singleton single;
public
static singleton getinstance()
}
}
return singleton;
}
兩種方法的區別:
第一種方式在方法上加了 synchronized ,雖然保證了執行緒安全,但是每次呼叫的時候都要進行同步,降低了效能,因為99%的情況下都是不需要同步的。
第二種方法使用了雙重檢查加鎖的方式,只有在第一次例項化的時候才需要同步。這種方法既保證了執行緒安全,又保證效能沒有大幅度下降。
2. 餓漢式
餓漢式,這個方法就比較簡單了。看名字我們也可以看出來,餓漢,那麼就代表著在未訪問之前就將單例類例項化好了。
下面是它的**實現:
//餓漢式單例類.在類初始化時,已經自行例項化
public
class
singleton1
private
static
final singleton1 single = new singleton1();
public
static singleton1 getinstance()
}
餓漢式在類建立的同時,就已經例項化了乙個靜態物件,因此是天生執行緒安全的。
執行緒安全
餓漢式天生執行緒安全,可以直接使用在多執行緒環境下。
懶漢式本身是非執行緒安全的,要實現執行緒安全請參考上面**。
效能餓漢式在類初始化的時候就會進行例項化單例類。 因此, 在初始化初期會占用較大資源。 但是相應帶來的好處就是在第一次呼叫的時候速度變快。
懶漢式的初始化策略就是 「 延遲載入 」 , 因此在第一次呼叫的時候會占用較大資源。而且在保證執行緒安全的解決方法中也存在不同的效能問題(區別請往上回顧一下)。
優點:因為只有乙個例項,減少了系統效能開支。
避免對記憶體的多重占用。
可以在系統中設定全域性訪問點,優化和共享資源訪問。
缺點:拓展困難。(沒有介面)
對測試不利。
與單一原則衝突。乙個類負責單一功能。而單例模式 將單例類的例項化和其他業務邏輯放在同乙個類中。
歡迎關注我的csdn:
歡迎聯絡我共同交流
每天一模式 單例模式
一 單例模式是為了控制類只有乙個例項物件,通常在以下兩種情況需要考慮使用單例模式 1 業務邏輯的需求 2 效能的考慮 二 單例模式的機構圖 三 單例模式的幾種實現形式 1 形式一 public class singleton2 public static singleton2 getinstance...
每天乙個設計模式之Factory
這點是使用工廠模式的主要目的。當client需要乙個類的例項時,它並不需要自己去例項化那個類,而是交給工廠去例項化。這樣client就不需要知道這個類是怎麼例項化的了。這樣物件的使用者和物件本身就解耦合了。如何實現 需要注意的是,客戶端既不知道,也不關心被例項化的類是什麼,而只是得到了乙個抽象類。而...
一天乙個設計模式 單例模式
1.餓漢模式public class sprivate static s s news public static s get 執行緒安全,載入時就初始化,根據需求來,此種用法最簡單2.懶漢模式public class sprivate static s s public static s get ...