天天看點

spring單例模式,多例模式,餓漢模式,懶漢模式(二)?

上篇文章介紹了單例模式,多例模式,有不明白的同學可以點進去先觀看:

​​spring單例模式,多例模式,餓漢模式,懶漢模式(一)?​​

這篇文章重點介紹餓漢模式懶漢模式,

餓漢模式:在加載對象時候,對象就會建立執行個體,為所有spring配置檔案中定義的bean都是生成的一個執行個體,天生線程安全的,多線程的情況下也不會出現問題。

懶漢模式:在擷取對象第一次請求的時候,才會建立執行個體。本身是線程不安全的,但有幾種實作線程安全的寫法。

1、餓漢模式:

因為執行個體被static和final修飾,在對象加載到記憶體的時候初始化,是以線程安全。

public class HungrySingleton {

    private String name;

    private static final HungrySingleton hungrySingleton = new HungrySingleton("張三");

    public HungrySingleton(String name){
        this.name = name;
    }

    public static HungrySingleton getInstance(){
        return hungrySingleton;
    }

}      

雖然這樣寫線程安全,但他還是有缺陷的,在getBean執行個體之前,不能不給他設定屬性和參數,這時候懶漢模式就出現了,可以通過雙重檢索可以實作線程安全。

2、懶漢模式:

private String name;
    private static LazySingleton lazySingleton;

    public LazySingleton(String name) {
        this.name = name;
    }

    public static LazySingleton getInstance() {
        //第一次通路的時候沒有對象,是以擷取對象
        if (lazySingleton == null) {
            lazySingleton = new LazySingleton("張三");
        }
        return lazySingleton;
    }

    public static LazySingleton getInstance2() {
        //保證線程安全
        synchronized (lazySingleton) {
            if (lazySingleton == null) {
                lazySingleton = new LazySingleton("張三");
            }
        }
        return lazySingleton;
    }

    public static LazySingleton getInstance3() {
        //保證線程安全,性能提升
        if (lazySingleton == null) {
            synchronized (lazySingleton) {
                if (lazySingleton == null) {
                    lazySingleton = new LazySingleton("張三");
                }
            }
        }
        return lazySingleton;
    }      
  1. getInstance()方法可以實作,第一次通路的時候沒有對象,是以為null的時候,擷取執行個體對象,但這種情況下多線程通路時候,會出現異常,導緻建立多個執行個體,如何解決呢?
  2. getInstance2()方法可以保證線程安全,上鎖之後,其他線程不可以進入,但這種情況會出現什麼問題呢?會一直上鎖,導緻沒必要的性能開銷,實際隻需要在第一次建立的上鎖。
  3. getInstance3()這就是為什麼要用雙重效驗,先判斷是否為null,然後在用synchronized上鎖實作線程安全。