標籤:
//餓漢式單例類.在類初始化時,已經自行執行個體化.//典型的空間換時間 public class Singleton1 { private Singleton1() {} private static final Singleton1 single = new Singleton1(); //靜態Factory 方法 public static Singleton1 getInstance() { return single; } }
//雙重鎖定public class Singleton { private volatile static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){ //先檢查執行個體是否存在,如果不存在才進入下面的同步塊 if(instance == null){ //同步塊,安全執行緒的建立執行個體 synchronized (Singleton.class) { //再次檢查執行個體是否存在,如果不存在才真正的建立執行個體 if(instance == null){ instance = new Singleton(); } } } return instance; }}/*被volatile修飾的變數的值,將不會被本地線程緩衝,所有對該變數的讀寫都是直接操作共用記憶體,從而確保多個線程能正確的處理該變數。注意:在java1.4及以前版本中,很多JVM對於volatile關鍵字的實現的問題,會導致“雙重檢查加鎖”的失敗,因此“雙重檢查加鎖”機制只只能用在java5及以上的版本。雙重校正鎖:麻煩,在當前Java記憶體模型中不一定都管用,某些平台和編譯器甚至是錯誤的,因為instance = new MaYun()這種代碼在不同編譯器上的行為和實現方式不可預知。*/
//餓漢改進/* 要想很簡單地實現安全執行緒,可以採用靜態初始化器的方式,它可以由JVM來保證線程的安全性。比如前面的餓漢式實現方式。但是這樣一來,不是會浪費一定的空間嗎?因為這種實現方式,會在類裝載的時候就初始化對象,不管你需不需要。如果現在有一種方法能夠讓類裝載的時候不去初始化對象,那不就解決問題了?一種可行的方式就是採用類級內部類,在這個類級內部類裡面去建立對象執行個體。這樣一來,只要不使用到這個類級內部類,那就不會建立對象執行個體,從而同時實現消極式載入和安全執行緒。 當getInstance方法第一次被調用的時候,它第一次讀取SingletonHolder.instance,導致SingletonHolder類得到初始化;而這個類在裝載並被初始化的時候,會初始化它的靜態域,從而建立Singleton的執行個體,由於是靜態域,因此只會在虛擬機器裝載類的時候初始化一次,並由虛擬機器來保證它的執行緒安全性。這個模式的優勢在於,getInstance方法並沒有被同步,並且只是執行一個域的訪問,因此延遲初始化並沒有增加任何訪問成本。*/public class Singleton { private Singleton(){} /** * 類級的內部類,也就是靜態成員式內部類,該內部類的執行個體與外部類的執行個體 * 沒有綁定關係,而且只有被調用到時才會裝載,從而實現了消極式載入。 */ private static class SingletonHolder{ /** * 靜態初始化器,由JVM來保證安全執行緒 */ private static Singleton instance = new Singleton(); } public static Singleton getInstance(){ return SingletonHolder.instance; }}
還有一種選擇
/*枚舉實現的Singleton */ enum TestSingleton3 { INSTANCE; public static TestSingleton3 getInstance() { return INSTANCE; } }
單例模式