? 單例模式的優(yōu)點(diǎn):?
– 由于單例模式只生成一個(gè)實(shí)例楣导,減少了系統(tǒng)性能開銷烦租,當(dāng)一個(gè)對(duì)象的產(chǎn)生需要 比較多的資源時(shí)豺鼻,如讀取配置沫勿、產(chǎn)生其他依賴對(duì)象時(shí)挨约,則可以通過在應(yīng)用啟動(dòng) 時(shí)直接產(chǎn)生一個(gè)單例對(duì)象,然后永久駐留內(nèi)存的方式來解決?
– 單例模式可以在系統(tǒng)設(shè)置全局的訪問點(diǎn)产雹,優(yōu)化環(huán)共享資源訪問诫惭,例如可以設(shè)計(jì) 一個(gè)單例類,負(fù)責(zé)所有數(shù)據(jù)表的映射處理
? 常見的五種單例模式實(shí)現(xiàn)方式:?
– 主要:?
????? 餓漢式(線程安全蔓挖,調(diào)用效率高夕土。 但是,不能延時(shí)加載。)?
????? 懶漢式(線程安全怨绣,調(diào)用效率不高角溃。 但是,可以延時(shí)加載篮撑。)?
– 其他:?
????? 雙重檢測(cè)鎖式(由于JVM底層內(nèi)部模型原因减细,偶爾會(huì)出問題。不建議使用)?
????? 靜態(tài)內(nèi)部類式(線程安全赢笨,調(diào)用效率高未蝌。 但是,可以延時(shí)加載)?
????? 枚舉單例(線程安全茧妒,調(diào)用效率高萧吠,不能延時(shí)加載)
? 餓漢式實(shí)現(xiàn)(單例對(duì)象立即加載)
public class SingletonDemo01 {
????private SingletonDemo01() {}; //私有化構(gòu)造器
????private static /*final*/ SingletonDemo01 instance = new SingletonDemo01();
????public static /*synchronized*/ SingletonDemo01 getInstance() {
????????return instance;
????}
}
? 餓漢式單例模式代碼中,static變量會(huì)在類裝載時(shí)初始化桐筏,此時(shí)也不會(huì)涉及多個(gè)線程對(duì)象訪問該對(duì)象的問題纸型。虛擬機(jī)保證只會(huì)裝載一次該類,肯定不會(huì)發(fā)生并發(fā)訪問的問題九昧。因此绊袋,可以省略synchronized關(guān)鍵字。
? 問題:如果只是加載本類铸鹰,而不是要調(diào)用getInstance()癌别,甚至永遠(yuǎn)沒有調(diào)用,則會(huì)造成資源浪費(fèi)
? 懶漢式實(shí)現(xiàn)(單例對(duì)象延遲加載)
public class SingletonDemo02 {
????private SingletonDemo02() {} //私有化構(gòu)造器
????private static SingletonDemo02 instance;
????public static synchronized SingletonDemo02 getInstance() {
????????if(instance==null) {
????????????instance = new SingletonDemo02();
????????}
????????return instance;
????}
}
? 要點(diǎn):?
– lazy load! 延遲加載蹋笼, 懶加載展姐! 真正用的時(shí)候才加載!
?? 問題:?
– 資源利用率高了剖毯。但是圾笨,每次調(diào)用getInstance()方法都要同步,并發(fā) 效率較低逊谋。
? 雙重檢測(cè)鎖實(shí)現(xiàn)
public class SingletonDemo03 {
????private SingletonDemo03() {}//私有化構(gòu)造器
????private static SingletonDemo03 instance;
????public static SingletonDemo03 getInstance() {
????????if(instance ==null) {
????????????SingletonDemo03 temp;//用于檢測(cè)instance是否為null
????????????synchronized(SingletonDemo03.class) {
????????????????temp=instance;
????????????????//instance有值便不再往下執(zhí)行
????????????????if(temp==null) {
????????????????????instance = new SingletonDemo03();
????????????????}
????????????}
????????}
????????return instance;
????}
}
? 靜態(tài)內(nèi)部類實(shí)現(xiàn)方式(也是一種懶加載方式)
public class SingletonDemo04 {
????private SingletonDemo04() {};//私有化構(gòu)造器
????private static class SingletonDemo{
????????private static final SingletonDemo04 instance = new SingletonDemo04();
????}
????public static SingletonDemo04 newInstance() {
????????return SingletonDemo.instance;
????}
}
? 要點(diǎn):?
– 外部類沒有static屬性擂达,則不會(huì)像餓漢式那樣立即加載對(duì)象。?
– 只有真正調(diào)用getInstance(),才會(huì)加載靜態(tài)內(nèi)部類胶滋。加載類時(shí)是線程 安全的板鬓。 instance是static final 類型,保證了內(nèi)存中只有這樣一個(gè)實(shí)例存在究恤,而且只能被賦值一次俭令,從而保證了線程安全性.?
– 兼?zhèn)淞瞬l(fā)高效調(diào)用和延遲加載的優(yōu)勢(shì)!
? 使用枚舉實(shí)現(xiàn)單例模式
public enum SingletonDemo05 {
????Instance;
}
? 優(yōu)點(diǎn):
?– 實(shí)現(xiàn)簡(jiǎn)單 – 枚舉本身就是單例模式部宿。由JVM從根本上提供保障抄腔!避免通過反射和反序列化的漏洞!?
? 缺點(diǎn):
?– 無延遲加載
? 如何選用??
– 單例對(duì)象占用資源少,不需要延時(shí)加載:?
????? 枚舉式 好于 餓漢式?
– 單例對(duì)象占用資源大赫蛇,需要延時(shí)加載:?
????? 靜態(tài)內(nèi)部類式 好于 懶漢式