1. 程式人生 > 其它 >【演算法】單例模式Singleton

【演算法】單例模式Singleton

單例模式Singleton

1.含義

單例模式:即一個類只能建立一個例項。

  • 只有一個例項 --> 不可以從類外new物件 --> 構造器私有化private --> 從類裡建立例項;
  • 這個物件供外部使用 --> 該例項的get方法 --> 沒有物件,隨著類載入 --> 方法宣告為static --> 靜態只能調靜態 --> 該例項也宣告為static;

2.實現

2.1 餓漢式

public class Singleton(){
    
    //1.私有化構造器;
    private Singleton();
    //2.建立例項;靜態;
    private static Singleton singleton = new Singleton();
    //3.獲取例項的公共方法;靜態;
    public static Singleton getSinggleton(){
        return singleton;
    }
}

特點
多執行緒安全:是;
lazy初始化:否;
類載入就建立例項,浪費記憶體;

2.2 懶漢式,執行緒不安全

public class Singgleton(){
    
    private Singleton();
    private static Singleton singleton; //延遲建立物件;
    public static Singleton getSingleton(){
        if(singleton == null){ //呼叫方法的時候沒有了再建立;
            singleton = new Singleton(); 
        }
        return singleton;
    }
}

特點
多執行緒安全:否 (當有多個執行緒操作時,可能會有多個執行緒都經過if判斷語句,就會建立多個例項,造成執行緒不安全);
lazy初始化:是;

2.3 懶漢式,執行緒安全

public class Singleton(){
    
    private Singleton();
    private static Singleton singleton;
    //給方法加鎖;
    public static synchronized Singleton getSingleton(){
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}

特點
多執行緒安全:是
lazy初始化:是
效率:低(每次都只是一個執行緒拿到鎖,呼叫方法,多個執行緒無法同時呼叫方法)

2.4 雙重檢驗鎖

public class Singleton(){
    
    private Singleton();
    //使用volatile宣告:
    //1.禁止指令重排;
    //2.保證變數修改後對所有執行緒可見,指示JVM,這個變數是共享且不穩定的,每次用要到主存中去讀取;
    private volatile static Singleton singleton();
    public static Singleton getSingleton(){
        if(singleton == null){  //判斷有沒有例項化過,沒有再進入加鎖模式,這樣絕大多數的都不會再進入了;
            synchronized(Singleton.class){
                if(singleton == null){ //再判斷一次,因為可能有多個執行緒都經過了前面的if,if不判斷就會建立多個物件了;
                    singleton == new Singleton();
                }
            }
        }
        return singleton;
    }
}

多執行緒安全:是
lazy初始化:是
效率:高

  • 第一個檢驗是為了效率;
  • 第二個檢驗為了執行緒安全;

直接加鎖再判斷 --> 效率低;
先判斷再加鎖 --> 效率高;