生活就要奮鬥
單例模式,按目的來分屬於創建型模式。是指一個類只有一個實例,該實例對象必須由該單例類自行創建。其特點:1.構造器私有化;2.只有一個實例對象;3.由單例類自行創建;4.對外提供一個全局的訪問方法。目的爲了節省內存資源、保證數據內容的一致性。直接看代碼,代碼中註釋,簡便易懂,如下:
<一>懶漢式單例模式:
/**
* 懶漢式單例:類加載時不生成實例對象,第一次去調用getInstance()方方法時,纔去創建實例對象。
*/
public class LazySingleton {
/* 實例對象 */
private static LazySingleton instance;
/* 構造器私有 */
private LazySingleton() {
}
/* 對外提供獲取單例實例的全局訪問方法 */
public static void getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
}
// 以下是懶漢式單例模式的變種:保證線程安全,但每次訪問都要同步,影響性能,消耗更多的資源。
private static volatile LazySingleton instanceVariant;
public static synchronized void getInstanceVariant() {
if (instance == null) {
instance = new LazySingleton();
}
}
}
<二>餓漢式單例模式:
/**
* 餓漢式單例:類一旦加載就初始化實例,是線程安全的;
* 但容易產生垃圾(當沒有調用這個實例時,由於該單例在類創建的同時就初始化了一個靜態的對象,所以容易造成內存空間的浪費)
*/
public class HungrySingleton {
/* 實例對象 */
private static final HungrySingleton instance = new HungrySingleton();
/* 構造器私有 */
private HungrySingleton() {
}
/* 供外部調用的方法 */
public static HungrySingleton getInstance() {
return instance;
}
}
<三>雙重校驗鎖單例模式:
/**
* 雙重校驗鎖單利:線程安全,延遲初始化
*/
public class DoubleLockSingleton {
/* volatile關鍵字能夠禁止指令重排,保證在寫操作沒有完成之前不能調用讀操作 */
private static volatile DoubleLockSingleton instance;
/* 構造器私有化 */
private DoubleLockSingleton() {
}
/* 雙重檢驗:第一次避免進入鎖,減少性能開銷;第二次進行同步,避免多線程問題,防止生成多個對象;
* 由於JVM中創建對象可能導致重排序,在多線程訪問下會存在問題,使用volatile修飾變量,禁止指令重排,有效解決這個問題 */
private static DoubleLockSingleton getInstance() {
if (instance == null) {
synchronized (DoubleLockSingleton.class) {
if (instance == null) {
instance = new DoubleLockSingleton();
}
}
}
return instance;
}
}
<四>靜態內部類單例模式:
/**
* 靜態內部類單例:充分利用了靜態內部類的特點。只有第一次調用getInstance()方法時,
* JVM才加載內部類實例化instance對象,只有一個線程可以獲取對象的初始化鎖,保證單例對象唯一,是線
* 程安全的。這也是目前比較推薦的方式。
*/
public class StaticInnerSingleton {
/* 構造器私有 */
private StaticInnerSingleton() {
}
/* 靜態內部類:在此創建單例對象 */
private static class SingletonInstance {
private static final StaticInnerSingleton instance = new StaticInnerSingleton();
}
/* 對外提供獲取單例實例的全局訪問方法 */
public static StaticInnerSingleton getInstance() {
return SingletonInstance.instance;
}
}
<五>枚舉單例模式:
/**
* 枚舉單例:是線程安全的。充分利用了枚舉的特性,簡單且高效。
* 實際開發中枚舉單例模式還是用到的比較少
*/
public enum EnumerateSingleton {
INSTANCE;
/* 可以省略此方法,通過Singleton.INSTANCE進行操作*/
public static EnumerateSingleton getInstance() {
return EnumerateSingleton.INSTANCE;
}
}
注:歡迎指教!