1. 程式人生 > 實用技巧 >JAVA封神之路-設計模式-單例模式

JAVA封神之路-設計模式-單例模式

為什麼要有單例模式

實際程式設計應用場景中,有一些物件其實我們只需要一個,比如執行緒池物件、快取、系統全域性配置物件等。這樣可以就保證一個在全域性使用的類不被頻繁地建立與銷燬,節省系統資源。

實現單例模式的幾個要點

    1. 首先要確保全域性只有一個類的例項。
      要保證這一點,至少類的構造器要私有化。
    2. 單例的類只能自己建立自己的例項。
      因為,構造器私有了,但是還要有一個例項,只能自己建立咯!
    3. 單例類必須能夠提供自己的唯一例項給其他類
      就是要有一個公共的方法能返回該單例類的唯一例項。

優點:

  • 1、在記憶體裡只有一個例項,減少了記憶體的開銷,尤其是頻繁的建立和銷燬例項(比如管理學院首頁頁面快取)。
  • 2、避免對資源的多重佔用(比如寫檔案操作)。

缺點:沒有介面,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來例項化。

使用場景:

  • 1、要求生產唯一序列號。
  • 2、WEB 中的計數器,不用每次重新整理都在資料庫里加一次,用單例先快取起來。
  • 3、建立的一個物件需要消耗的資源過多,比如 I/O 與資料庫的連線等。

1、餓漢式—靜態常量方式(執行緒安全)

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}

類載入時就初始化例項,避免了多執行緒同步問題。天然執行緒安全。

2、懶漢式(執行緒不安全)

public class Singleton {
    private static Singleton singleton;
    private Singleton() {}
    public static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

這是最基本的實現方式,第一次呼叫才初始化,實現了懶載入的特性。多執行緒場景下禁止使用,因為可能會產生多個物件,不再是單例。

3、懶漢式(執行緒安全,方法上加同步鎖)

public class Singleton {
    private static Singleton singleton;
    private Singleton() {}
    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

和上面 懶漢式(執行緒不安全)實現上唯一不同是:獲取例項的getInstance()方法上加了同步鎖。保證了多執行緒場景下的單例。但是效率會有所折損,不過還好。

4、雙重校驗鎖(執行緒安全,效率高)

public class Singleton {
	private volatile static Singleton singleton;
	private Singleton() {}
	public static Singleton getSingleton() {
		if (singleton == null) {
			synchronized (Singleton.class) {
				if (singleton == null) {
						singleton = new Singleton();
				}
			}
		}
		return singleton;
	}
}

此種實現中不用每次需要獲得鎖,減少了獲取鎖和等待的事件。
注意volatile關鍵字的使用,保證了各執行緒對singleton靜態例項域修改的可見性。