通常採用單例模式就是爲了知足「只建立一個類」的須要。安全
單例模式有兩個特色:
(1)一個類僅有一個實例
(2)僅有一個全局訪問點線程
一、餓漢式
所謂餓漢式,是指這個類的實例在類加載階段就已經建立出來了。code
public class Singleton1 { //在類的內部實例化一個實例 private static final Singleton1 instance = new Singleton1(); //隱藏構造方法 private Singleton1() { } //對外開放一個獲取實例的方法 public static Singleton1 getInstance(){ return instance; } }
固然也可使用static代碼塊。(注意這裏的final,看網上有各類寫法,加或者不加的都有,我認爲這裏能夠加,這樣getInstance方法裏就不須要判空了)對象
這種方式雖然可以有效避免線程安全的問題,可是卻可能形成沒必要要的浪費,由於也許這個實例並不須要用到,或者就用到一兩次,卻要一直佔用內存。內存
二、靜態內部類get
public class InnerClassSingleton { //在靜態內部類中實例化對象 private static class SingletonHolder{ private static final InnerClassSingleton instance = new InnerClassSingleton(); } //隱藏構造方法 private InnerClassSingleton(){ } //對外提供訪問方法 public static final InnerClassSingleton getInstance() { return SingletonHolder.instance; } }
三、懶漢式
所謂懶漢式,就是在使用時才加載,比較「懶一些」。class
public class Singleton2 { private static Singleton2 instance; private Singleton2(){ } public static Singleton2 getInstance(){ //在對象被使用時才實例化 if (instance == null) instance = new Singleton2(); return instance; } }
注意:加上synchronized關鍵字就能夠保證線程安全。效率
public class Singleton2 { private static Singleton2 instance; private Singleton2(){ } public static synchronized Singleton2 getInstance(){ //在對象被使用時才實例化 if (instance == null) instance = new Singleton2(); return instance; } }
四、固然上述方式效率比較低,由於synchronized鎖的範圍太大了程序
public class Singleton2 { private static Singleton2 instance; private Singleton2(){ } public static Singleton2 getInstance(){ //在對象被使用時才實例化 synchronized (Singleton2.class){ if (instance == null) instance = new Singleton2(); return instance; } } }
這樣就縮小了鎖的範圍,可是這種方式依然存在問題,由於Java內存模型的機制,程序可能會崩潰,所以就要用到volatile。方法
五、使用volatile
public class Singleton2 { private static volatile Singleton2 instance; private Singleton2(){ } public static Singleton2 getInstance(){ //在對象被使用時才實例化 if (instance == null){ synchronized (Singleton2.class){ if (instance == null) instance = new Singleton2(); return instance; } } } }
六、枚舉式
public enum Singleton3 { INSTANCE; Singleton() { } }