Java 代碼編寫單例模式總結

  手寫一個單例模式是 Java 面試中常見的問題,不少時候咱們更偏向於簡單的寫一個餓漢或飽漢模式,深刻研究的甚少,這裏列舉三種實現方式,並對各自的優缺進行分析。面試

1. 餓漢式安全

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

  這種方式要求類在加載時就要實例化,因此程序開始時就可能產生許多暫時沒有不會用到的實例,減緩了程序初始化過程。但它寫法簡便,線程安全,是完成相關題目時的首選,同時這也是部分 IDE 工具在自動建立單例的時候默認採用的寫法。工具

2. 飽漢式spa

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

  首次獲取該類實例時才進行實例化,符合程序設計要求,同時結構還算清晰,通常也能準確編寫。但這種實現方式自己線程不安全,須要用 synchronized 關鍵字作方法同步。線程

3.雙重鎖式設計

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

  其實這種方式能夠看做是飽漢模式的一種改進,主要考慮到同步是一種高開銷的操做,應該儘可能減小同步的內容,因此這裏在獲取實例的靜態方法裏面作了代碼塊同步,再也不像以前,每次啓用 getInstance 方法獲取實例時,無論實例是否已經存在都會對後續操做進行同步處理。這裏先對實例是否存在進行判斷,當確實例不存在確實須要進行實例化操做時再作後續操做,而在入同步代碼塊前一刻始終有可能另外一個線程已經對其完成了實例化,因此還要再作第二次判斷,volatile 能保證各線程對 instance 進行操做時的可見性,即保證每次進行判斷時 instance 的值都是最新的。code

相關文章
相關標籤/搜索