JAVA封神之路-設計模式-單例模式
阿新 • • 發佈:2020-11-24
為什麼要有單例模式
實際程式設計應用場景中,有一些物件其實我們只需要一個,比如執行緒池物件、快取、系統全域性配置物件等。這樣可以就保證一個在全域性使用的類不被頻繁地建立與銷燬,節省系統資源。
實現單例模式的幾個要點
- 首先要確保全域性只有一個類的例項。
要保證這一點,至少類的構造器要私有化。 - 單例的類只能自己建立自己的例項。
因為,構造器私有了,但是還要有一個例項,只能自己建立咯! - 單例類必須能夠提供自己的唯一例項給其他類
就是要有一個公共的方法能返回該單例類的唯一例項。
優點:
- 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靜態例項域修改的可見性。