單例的四種實現(xiàn)方式
一畦娄、餓漢方式
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance() {
return instance;
}
}
- 優(yōu)點:代碼簡單节吮,避免多線程同步問題
- 缺點:類的初始化階段就會導致實例化弛房,無法延遲實例化开睡。
觸發(fā)類進行初始化條件
- 使用new關鍵字創(chuàng)建一個對象
- 讀取/設置一個類的靜態(tài)字段
- 使用反射調用類
- 初始化一個類時候害驹,如果其父類還未被初始化鞭呕,會優(yōu)先觸發(fā)其父類初始化
- 當jvm啟動時,用于指定執(zhí)行的主類
二宛官、懶漢方式(DCL)
public class Singleton {
private static volatile Singleton singleton = null;
private Singleton(){}
public static Singleton getSingleton(){
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
- 優(yōu)點:延遲單例實例化葫松,以DCL方式提高線程并發(fā)效率
- 注意:JDK1.5引入關鍵字volatile才能達到正常單例效果。對一個volatile域的寫底洗,happens- before 于任意后續(xù)對這個volatile域的讀腋么,即保證了讀寫操作不會亂序。
三亥揖、靜態(tài)內部類
public class Singleton {
/**
* 是靜態(tài)內部類珊擂,該內部類的實例與外部類的實例沒有綁定關系,
* 而且只有被調用到才會裝載费变,從而實現(xiàn)了延遲加載
*/
private static class SingletonHolder {
//保證了線程安全
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
- 優(yōu)點1:線程安全——利用了classloader機制保證只有一個線程來初始化類摧扇。
- 優(yōu)點2:延遲實例化——只有通過getInstance方法才會觸發(fā)內部類被初始化腹缩。
四凤类、枚舉
public enum Singleton {
INSTANCE;
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
在JDK1.5加入enum特性
使用enum實現(xiàn)單例優(yōu)點:
- 線程安全(構造方法)——無序擔心DCL帶來的影響
- 不因為序列化而產生新實例
- 防止反射攻擊