單例模式 即記憶體只會建立乙個物件也只建立一次物件的設計模式。
那為什麼我們要使用單例呢,大家都知道頻繁的建立物件會讓記憶體飆公升,而單例模式會讓記憶體只使用這乙個物件,
單例模式的型別
懶漢式:(好懶啊,什麼時候用我就什麼時候建立好了) 只有真正使用物件的時候才會建立單例物件
餓漢式:(好餓啊,趕緊建立出來吧)在類載入的時候,就建立好了,
懶漢式的建立方式:
public class singleton()
public static getinstance()
return singleton
}}
如果在多執行緒的環境下,上面寫的就不是那麼好了,那麼看他的公升級版
public class singleton()
//加了乙個鎖,這下執行緒安全了吧
public synchronized static getinstance()
return singleton
}}
但是 每次獲取物件都要獲取鎖,併發的效能差到了極點了。那好吧,我改改
public class singleton
public static singleton getinstance() }}
return singleton;
}}
這麼寫 就解決了併發安全和效能問題。這種寫法也叫雙重檢驗(double check)+鎖(lock),這下沒問題了吧?
nonono..咱們忽略了一點,指令重排。
這個東西可氣人了。jvm在保證最後結果正確的情況下,可能不按照你寫的順序執行語句。那我們怎麼辦啊?乙個關鍵字搞定
volatile 。別看他就乙個關鍵字。他作用大著呢!l
1.使用 volatile 關鍵字修飾的變數,可以保證其指令執行的順序與程式指明的順序一致,不會發生順序變換
2.用 volatile 關鍵字修飾的變數,可以保證其記憶體可見性,即每一時刻執行緒讀取到該變數的值都是記憶體中最新的那個值,執行緒每次操作該變數都需要先讀取該變數。
那最終的**是什麼樣呢?
public class singleton
public static singleton getinstance() }}
return singleton;
}}
餓漢式比較簡單啦
直接上**
public class singleton
public static singleton getinstance()
}
你以為結束了?沒有呢
還有一種寫法
public enum singleton
public static void main(string args)
public synchronized static void test()
}
這是啥?列舉,有啥好處?
1**少,只需要三行**不用
2.天然的執行緒安全與單一例項
3.還有一點是上面那兩種辦法都媲美不了的。就是列舉可不怕你的反射,你的序列化反序列化來破壞我的單例。
列舉類預設繼承了 enum 類,在利用反射呼叫 newinstance() 時,會判斷該類是否是乙個列舉類,如果是,則丟擲異常。
在讀入 singleton 物件時,每個列舉型別和列舉名字都是唯一的,所以在序列化時,僅僅只是對列舉的型別和變數名輸出到檔案中,在讀入檔案反序列化成物件時,使用 enum 類的 valueof(string name) 方法根據變數的名字查詢對應的列舉物件。所以,在序列化和反序列化的過程中,只是寫出和讀入了列舉型別和名字,沒有任何關於物件的操作。
那就到這裡了。。。
我眼中的單例模式
說到單例模式,網上搜尋出來的結果是多如牛毛,但這不影響我也來湊熱鬧的心情。任何事情都是要親身去體會了,才能加深自己的理解。本著不斷學習進取的精神,我很想可以站在牛人的肩膀上,哪怕是仰視牛人的情況下,我也想發揮自己的餘熱。記錄下自己學習的足跡,權當自己未來細細回味也好。不過說真的,自己試著去組織語言來...
我眼中的MVC模式
首先,我們看看維基百科上的解釋 mvc模式 model view controller 是軟體工程中的一種軟體架構模式,把軟體系統分為三個基本部分 模型 model 檢視 view 和控制器 controller mvc模式最早由trygve reenskaug在1978年提出,是施樂帕羅奧多研究中...
我理解的設計模式 單例模式
單例模式 singleton pattern 什麼是單例模式,四人幫的書裡面這麼定義 保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點。可以這麼理解 在乙個程序裡,這個類只會被例項化一次,而且可以很方便的被呼叫。實現 惡漢式 載入類的時候,在類的內部定義乙個例項,外部呼叫則開放給乙個靜態函式。...