單例模式
核心作用:保證一個類只有一個實例并且提供一個訪問該實例的全局訪問點
優(yōu)點:
- 減少系統(tǒng)開銷
- 優(yōu)化共享資源訪問
- 餓漢式
public class EagerSingleton{
// 私有化構(gòu)造器
private EagerSingleton(){
}
// 類初始化時創(chuàng)建實例(無并發(fā)問題,不可懶加載)
private static Singleton instance = new EagerSingleton();
// 公開訪問點(沒有synchronized)
public static EagerSingleton getInstance(){
return instance;
}
/**
* 線程安全 不可懶加載
* 因為不可懶加載,如果對象空間占用大,長時間不用會造成空間浪費
*/
}
- 懶漢式
public class LazySingleton{
// 私有化
private LazySingleton(){
}
// 延遲加載
private static LazySingleton instance;
// 需要synchronized, 防止一開始有多個線程同時進入if判斷
public static synchronized LazySingleton getInstance(){
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
/**
* 線程安全 延遲加載
* 但是鎖方法,效率低
*/
}
- DCL懶漢式
public class DCLLazySingleton{
// 私有化
private DCLLazySingleton(){
}
// 延遲加載
private volatile static DCLLazySingleton instance;
// 縮小synchronized的范圍,只有第一次獲取需要進入鎖,提高效率
public static DCLLazySingleton getInstance(){
if(instance == null){
synchronized(DCLLazySingleton.class){
if(instance == null){
instance = new LazySingleton();
}
}
}
return instance;
}
}
/**
* 線程安全 延遲加載
* 只對第一次進來需要鎖,提高效率
* 但是不是原子性操作
* 分為以下:
* 1. 分配內(nèi)存
* 2. 執(zhí)行構(gòu)造方法
* 3. 指向地址
* 在指令重排的情況下有可能第一個進程在還沒有出去的情況下,
* 第二個已經(jīng)判定不為空直接出去了,
* 實例化不完整
* 所有需要添加volatile關(guān)鍵字,可以直接讀取最新的值(內(nèi)存中的值)
*/
- 靜態(tài)內(nèi)部類實現(xiàn)
public class Singleton{
private Singleton(){
}
// 靜態(tài)內(nèi)部類
private static class InnerClass{
private static final Singleton instance = new Sinpleton();
}
// 訪問點
public static Singleton getInstance(){
return InnerClass.instance;
}
/**
* 線程安全 延遲加載
* 因為內(nèi)部沒有static變量所以初始化時不會直接加載
* 當(dāng)調(diào)用getInstance()方法時才會加載靜態(tài)內(nèi)部類加載內(nèi)部類里面的靜態(tài)Singleton
* 因為是static final所有保證了instance只有一個實例
*/
}
- 枚舉
public enum EnumSingleton{
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}
/**
* 線程安全 不可延遲加載
* 但是可以防止反射破壞
*/
// getInstance 源碼:
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, clazz, modifiers);
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}
要根據(jù)不同的情況考慮不同的實現(xiàn)方法