================================
©Copyright 蕃薯耀 2022-05-20
https://www.cnblogs.com/fanshuyao/
一、餓漢模式
public class Hunger {
/**
* 增加final關鍵字,避免被修改
*/
private static final Hunger hunger = new Hunger();
/**
* 私有化,避免建立對象
*/
private Hunger() {};
/**
* 提供擷取對象的方法
* @return
*/
public static Hunger get() {
return hunger;
}
}
二、餓漢模式(靜态塊)
可以通過配置檔案對執行個體進行初始化
import lqy.utils.PropertiesUtils;
public class HungerStatic {
private static final HungerStatic hungerStatic;
private String name;
/**
* 私有化,避免建立對象
*/
private HungerStatic(String name) {
this.name = name;
};
static {
String name = PropertiesUtils.readKeyValue("config.properties", "name");
hungerStatic = new HungerStatic(name);
}
/**
* 提供擷取對象的方法
* @return
*/
public static HungerStatic get() {
//System.out.println(hungerStatic);
return hungerStatic;
}
/*
@Override
public String toString() {
return "HungerStatic [name=" + name + "]";
}
*/
}
三、懶漢模式 - 同步方法
public class LazySafe {
private static LazySafe lazySafe;
private LazySafe() {}
public static synchronized LazySafe get() {
if(lazySafe == null) {
lazySafe = new LazySafe();
}
return lazySafe;
}
}
四、懶漢模式 - 同步塊
public class LazySync {
/**
* 需要加volatile防止指令重排
*/
private static volatile LazySync lazySync;
private LazySync() {}
public static LazySync get() {
synchronized (LazySync.class) {
if(lazySync == null) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
lazySync = new LazySync();
}
}
return lazySync;
}
}
五、懶漢模式 - 雙重判斷
public class LazySyncDouble {
/**
* 需要加volatile防止指令重排
*/
private static volatile LazySyncDouble lazySyncDouble;
private LazySyncDouble() {}
public static LazySyncDouble get() {
if(lazySyncDouble == null) {
synchronized (LazySyncDouble.class) {
if(lazySyncDouble == null) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
lazySyncDouble = new LazySyncDouble();
}
}
}
return lazySyncDouble;
}
}
六、懶漢模式 - 内部類
/**
* Inner是一個内部靜态類,當外部類 LazyInner 被加載的時候,并不會建立 Inner執行個體對象。
* 隻有當調用 get() 方法時,Inner才會被加載,這個時候才會建立 instance。
* instance 的唯一性、建立過程的線程安全性,都由 JVM 來保證。
* 是以,這種實作方法既保證了線程安全,又能做到延遲加載。
* @author islee
*
*/
public class LazyInner {
private LazyInner() {}
/**
* 靜态内部類
*
*/
private static class Inner{
private static final LazyInner lazyInner = new LazyInner();
}
public static LazyInner get() {
return Inner.lazyInner;
}
}
七、枚舉【最安全方式】
最安全,能預防反射和反序列化的安全問題
/**
* Java虛拟機會保證枚舉類型不能被反射并且構造函數隻被執行一次。
* [最安全],其他的會存在反射和反序列化的安全問題
*
*/
public class SingletonEnum {
private SingletonEnum() {}
private enum SingletonHolder {
INSTANCE;
private final SingletonEnum singletonEnum;
private SingletonHolder() {
singletonEnum = new SingletonEnum();
}
private SingletonEnum get() {
return singletonEnum;
}
}
public static SingletonEnum get() {
return SingletonHolder.INSTANCE.get();
}
}
測試:
import lqy.design.singleton.SingletonEnum;
public class SingletonEnumTest {
public static void singletonEnum() {
long startTime = System.currentTimeMillis();
for(int i=0; i<15; i++){
new Thread(()-> {
System.out.println(SingletonEnum.get());
}).start();
}
long endTime = System.currentTimeMillis();
System.out.println("耗時:" + (endTime - startTime));
}
public static void main(String[] args) {
singletonEnum();
}
}
(時間寶貴,分享不易,捐贈回饋,^_^)
================================
©Copyright 蕃薯耀 2022-05-20
https://www.cnblogs.com/fanshuyao/
今天越懶,明天要做的事越多。