DCL(雙重檢查加鎖)
public class Singleton
{
//volatile確保對singleton的讀寫操作不會同時進行,不會出現讀取到錯誤值的情況
//如果不用volatile進行修飾,可能會出現在getInstance()時讀取到錯誤值的情況,因爲new不是原子操作,包含了好幾步操作,這幾步操作很可能是這樣:使singleton對象與引用相關聯發生在初始化singleton之前,這種操作在單線程下看對後面是不會有影響的,但是多線程會造成另一個線程調用getInstance()時發現singleton不是null,但其實還沒有初始化完畢導致讀到錯誤的值
private volatile Singleton singleton = null;
//建議所有的單例模式構造器都是私有的,防止在類外部建立多個實例
private Singleton() {}
public static Singleton getInstance() {
//第一次檢查是否已經生成了實例
if (singleton== null) {
synchronized (Singleton.class) {
//如果有多個線程獲得了這個鎖,第二次檢查確保第二個線程進來不會再次生成新的實例
if (singleton== null) {
singleton= new Singleton();
}
}
}
return singleton;
}
}
提前初始化模式
public class Singleton
{
//在類被加載的時候就會生成singleton實例,所以不會有線程安全問題
private static Singleton singleton = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return singleton;
}
}
延長初始化佔位類模式
public class Singleton {
//加載Singleton類的時候不會加載SingletonHolder類,只有第一次訪問SingletonHolder類時纔會加載
private static class SingletonHolder {
private static Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
枚舉實現單例模式
public enum Singleton{
INSTANCE;
public void test() {
System.out.println("你調用了test()!");
}
}
枚舉類默認構造方法就是私有的,並且只能是私有的.