Java單例模式的思考

單例模式的特徵

  • 私有的構造函數
  • 提供靜態變量
  • 提供靜態的獲取實例方法

單例模式六種寫法

  • 餓漢式單例模式
/**
 * @author: lilinjie
 * @date: 2019-08-27 13:37
 * @description: 餓漢式
 */
public class Singleton {
    private static Singleton sInstance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return sInstance;
    }
}
  • 懶漢式單例模式
/**
 * @author: lilinjie
 * @date: 2019-08-27 13:37
 * @description: 懶漢式
 */
public class Singleton {
    private static Singleton sInstance = null;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (sInstance == null) {
            sInstance = new Singleton();
        }
        return sInstance;
    }
}
  • 懶漢式單例模式(線程安全)
/**
 * @author: lilinjie
 * @date: 2019-08-27 13:37
 * @description: 懶漢式(線程安全)
 */
public class Singleton {
    private static Singleton sInstance = null;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (sInstance == null) {
            sInstance = new Singleton();
        }
        return sInstance;
    }
}
  • 雙重檢查鎖實現單例模式
/**
 * @author: lilinjie
 * @date: 2019-08-27 13:37
 * @description: 雙重檢查鎖
 */
public class Singleton {
    private static volatile Singleton sInstance = null;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (sInstance == null) {
            synchronized (Singleton.class) {
                if (sInstance == null) {
                    sInstance = new Singleton();
                }
            }
        }
        return sInstance;
    }
}
  • 靜態內部類實現單例模式
/**
 * @author: lilinjie
 * @date: 2019-08-27 13:37
 * @description: 靜態內部類實現單例模式
 */
public class Singleton {
    
    private Singleton() {
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
}
  • 枚舉實現單例模式
/**
 * @author: lilinjie
 * @date: 2019-08-27 13:37
 * @description: 枚舉實現單例模式
 */
public enum Singleton {
    INSTANCE;

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
  • CAS操作實現單例
// CAS操作實現單例
public class Singleton {
    private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<>();

    public Singleton getInstance() {
        for (; ; ) {
            Singleton singleton = INSTANCE.get();
            if (singleton != null) {
                return singleton;
            }
            singleton = new Singleton();
            if (INSTANCE.compareAndSet(null, singleton)) {
                return singleton;
            }
        }
    }
}

單例模式注意點

  • 反射可能會破壞單例模式,通過反射可以強制調用構造函數,生成對象實例,這裏構造函數內部可以加入判斷,如果對象實例已存在,則拋出異常,禁止再次調用。
  • 反序列化可能會破壞單例,反序列還的過程中,會重新生成對象,這裏可以在單例類中定義一個readResolve()方法,內部返回已創建的實例,使其在反序列化的過程中調用該方法,仍然返回之前的實例。
  • 克隆可能會破壞單例模式,通過重寫clone方法,返回已創建的實例
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章