單例模式常常會是咱們學習設計模式的第一個模式。在spring框架下,Bean的默認初始化也是單例模式。 單例模式常見的有懶漢模式和餓漢模式。 先來講說這兩個命名由來。 懶漢模式: lazily 餓漢模式: early 感受是音譯。。。java
通常狀況下,單例對象應該是無狀態的,也就是說沒有成員變量字段,或者說成員變量不發生變化。 而有狀態的對象,每每在系統中是多例存在。不一樣的實例擁有不一樣的狀態。spring
public class Singleton{
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static getInstance(){
return INSTANCE;
}
}
複製代碼
優勢: 線程安全,實現簡單,容易理解。 缺點: 空間浪費。在啓動的時候就會建立實例。設計模式
public class Singleton {
private static Singleton INSTANCE;
static {
INSTANCE = new Singleton();
}
private Singleton(){}
public static Singleton getInstance() {
return INSTANCE;
}
}
複製代碼
這種方式和第一種沒有區別。安全
public class Singleton {
private static Singleton INSTANCE;
private Singleton(){}
public static Singleton getInstance(){
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
複製代碼
這種方式實現了懶加載,在調用實例對象的時候才構造。可是帶來的問題是線程不安全。若是是在多線程環境下,會生成多個實例。多線程
public class Singleton {
private static Singleton INSTANCE;
private Singleton(){}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
複製代碼
要解決線程安全問題,最簡單的作法是讓方法加個同步。這樣一來即可保證線程安全,可是帶來的問題是性能損耗。由於其實只有在第一次構造的時候須要同步,之後獲取的時候不須要同步的。框架
public class Singleton {
private static Singleton INSTANCE;
private Singleton(){}
public static Singleton getInstance() {
if (INSTANCE != null) {
return INSTANCE;
}
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
return INSTANCE;
}
}
複製代碼
這種方式就比較完美了。作一個雙重檢查,保證了在第一次構造實例的時候的線程安全。同時也保證了以後獲取實例對象不須要同步。性能
public class Singleton {
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton(){}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
複製代碼
這種方式表面上看和餓漢模式很類似,可是其實也是實現了懶加載。巧妙之處在於利用了內部類啓動機制保證了線程安全。我的比較推薦以上兩種寫法。學習
public enum Singleton {
INSTANCE;
}
複製代碼
坊間還有使用枚舉類來實現的例子,雖然也能達到單例的效果,同時也是線程安全。可是我的並不推崇這種用法,緣由在於枚舉並非設計來實現單例的,理解起來會讓人困惑。spa