天天看點

單例模式的寫法

單例模式的七種寫法

  1. 懶漢,線程不安全
  2. 懶漢,線程安全
  3. 餓漢
  4. 靜态内部類(推薦)
  5. 枚舉(推薦)
  6. 雙重校驗鎖
  7. CAS(推薦)

1.懶漢,線程不安全

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  

    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}  
           

2.懶漢,線程安全

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}  
           

3.餓漢

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
} 
           

4.靜态内部類

public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
} 
           

5.枚舉

public enum Singleton {  
    INSTANCE;   
} 
           

6.雙重校驗鎖

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}  
           

7.CAS

CAS是項樂觀鎖技術,當多個線程嘗試使用CAS同時更新同一個變量時,隻有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程并不會被挂起,而是被告知這次競争中失敗,并可以再次嘗試。

用CAS的好處在于不需要使用傳統的鎖機制來保證線程安全,CAS是一種基于忙等待的算法,依賴底層硬體的實作,相對于鎖它沒有線程切換和阻塞的額外消耗,可以支援較大的并行度。

CAS的一個重要缺點在于如果忙等待一直執行不成功(一直在死循環中),會對CPU造成較大的執行開銷。

public class SingletonCAS {

    private static final AtomicReference<SingletonCAS> instance = new AtomicReference<>();

    private SingletonCAS() {
    }

    public static SingletonCAS getInstance() {
        for (; ; ) {
            SingletonCAS singletonCAS = instance.get();
            if (null != singletonCAS) {
                return singletonCAS;
            }
            singletonCAS = new SingletonCAS();
            if (instance.compareAndSet(null, singletonCAS)) {
                return singletonCAS;
            }
        }
    }
}
           

繼續閱讀