來源於headfirst設計模式html
單例模式的性能指標:lazy(是否延遲實例化),線程安全java
1、延遲實例化,同步(synchronized)方法-->因爲是單例更須要考慮處理問題須要考慮的同步問題,延遲實例化主要是面向資源敏感的對象設計模式
1 public class Singleton { 2 3 private static Singleton uniqueinstance;//惟一的實例變量 4 5 private Singleton() {//私有的初始化方法 6 } 7 8 public static synchronized Singleton getInstance() { 9 //實例的獲取方法,將普通的初始化方法變爲得到方法 10 if (uniqueinstance== null) { 11 uniqueinstance= new Singleton();//直接在類內部初始化 12 } 13 return instance; 14 } 15 }
2、直接實例化(靜態工廠方法)安全
1 public class Singleton { 2 3 private static Singleton uniqueInstance = new Singleton(); 4 //直接建立單例 5 private Singleton() { 6 } 7 8 public static Singleton getInstance() { 9 10 return uniqueInstance; 11 } 12 }
3、雙重檢驗加鎖,雙重檢查鎖定模式首先驗證鎖定條件(第一次檢查),只有經過鎖定條件驗證才真正的進行加鎖邏輯並再次驗證條件(第二次檢查)。-->用來減小併發系統中競爭和同步的開銷。[http://zh.wikipedia.org/wiki/%E5%8F%8C%E9%87%8D%E6%A3%80%E6%9F%A5%E9%94%81%E5%AE%9A%E6%A8%A1%E5%BC%8F]多線程
public class Singleton { private volatile static Singleton instance = null;//volatile變量 private Singleton() { } public static Singleton getInstance() { if (instance == null) {//只有首次初始化時纔用到了同步模塊,避免了同步對資源的浪費 synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
volatile變量的做用[參考:http://blog.csdn.net/orzorz/article/details/4319055]併發
用在多線程,爲了同步變量。在Java內存模型中,有main memory,每一個線程也有本身的memory (例如寄存器)。爲了性能,一個線程會在本身的memory中保持要訪問的變量的副本。這樣就會出現同一個變量在某個瞬間,在一個線程的memory中的值可能與另一個線程memory中的值,或者main memory中的值不一致的狀況。
一個變量聲明爲volatile,就意味着這個變量是隨時會被其餘線程修改的,所以不能將它cache在線程memory中。synchronized的優點在於其能夠把方法或者代碼塊變爲原子操做,而volatile沒法。jvm
4、枚舉單例,上面的方法都有一個問題就是反序列化,破壞了單例的特性,你能夠去查詢使用readResolve(),但比較麻煩,推薦使用Java的這個新特性——枚舉類型。它具備內置的序列化支持和線程安全支持。ide
public
enum
EasySingleton{
性能
INSTANCE;
}
在 java 垃圾回收中,描述了jvm運行時刻內存的分配。其中有一個內存區域是jvm虛擬機棧,每個線程運行時都有一個線程棧,線程棧保存了線程運行時候變量值信息。當線程訪問某一個對象時候值的時候,首先經過對象的引用找到對應在堆內存的變量的值,而後把堆內存變量的具體值load到線程本地內存中,創建一個變量副本,以後線程就再也不和對象在堆內存變量值有任何關係,而是直接修改副本變量的值,在修改完以後的某一個時刻(線程退出以前),自動把線程變量副本的值回寫到對象在堆中變量。這樣在堆中的對象的值就產生變化了。優化
[http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html]
5、各類優化
/** * 基於內部類的單例模式 Lazy 線程安全 * 優勢: * 一、線程安全 * 二、lazy * 缺點: * 一、待發現 * * @author laichendong * @since 2011-12-5 */ public class SingletonFive { /** * 內部類,用於實現lzay機制 */ private static class SingletonHolder{ /** 單例變量 */ private static SingletonFive instance = new SingletonFive(); } /** * 私有化的構造方法,保證外部的類不能經過構造器來實例化。 */ private SingletonFive() { } /** * 獲取單例對象實例 * * @return 單例對象 */ public static SingletonFive getInstance() { return SingletonHolder.instance; } }
http://www.cnblogs.com/coffee/archive/2011/12/05/inside-java-singleton.html
這種方式利用靜態內部類的優點,既是後實例化的又是線程安全的。