常規(guī)方式
- 懶漢式 DCL「雙重檢測鎖:Double Checked Lock」
public class Singleton {
private static volatile Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
// 延遲初始化
instance = new Singleton();
}
}
}
return instance;
}
}
優(yōu)點:線程安全猴贰;延遲加載;效率較高呐舔。
缺點:由于volatile關(guān)鍵字會屏蔽Java虛擬機所做的一些代碼優(yōu)化蠢甲,略微的性能降低。
- 餓漢式(靜態(tài)常量)
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
缺點:使用靜態(tài)final的實例對象或者使用靜態(tài)代碼塊依舊不能解決在反序列化递礼、反射、克隆時重新生成實例對象的問題(見參考1)
枚舉方式
- 餓漢式枚舉單例
public enum T {
SPRING,SUMMER,AUTUMN,WINTER;
}
// 反編譯之后可知枚舉中的各個枚舉項是通過static來定義的
public final class T extends Enum
{
//省略部分內(nèi)容
public static final T SPRING;
public static final T SUMMER;
public static final T AUTUMN;
public static final T WINTER;
private static final T ENUM$VALUES[];
static
{
SPRING = new T("SPRING", 0);
SUMMER = new T("SUMMER", 1);
AUTUMN = new T("AUTUMN", 2);
WINTER = new T("WINTER", 3);
ENUM$VALUES = (new T[] {
SPRING, SUMMER, AUTUMN, WINTER
});
}
}
- 懶漢式枚舉單例(枚舉+內(nèi)部類)
enum LanguageEnum {
INSTANCE;
private static class Language {
public String realName(String name) {
return "Language " + name;
}
}
private Language instance = null;
private LanguageEnum() {
instance = new Language();
}
// 實際對外開放的兩個方法
public Language getLanguage() {
return instance;
}
public void printlnLanguageName(String name) {
String str = getLanguage().realName(name);
System.out.println(str);
}
}
demo
使用枚舉的好處:
- 定義的代碼少羹幸,主要是系統(tǒng)幫忙做了文中反編譯那部分脊髓。
- 線程安全