設計模式-Java實現單例模式

hu斌發表於2017-10-09

設計模式-Java實現單例模式

單例模式是一種常見的設計模式,許多時候系統只需要一個全域性的物件時可以運用單例模式,它確保在系統中某種類只能有一個例項它的特點有:

  • 類最多隻能擁有一個例項物件
  • 類自己建立唯一例項物件
  • 類向外提供獲取唯一例項物件的方法

單例模式實現方法

單例類通常擁有一個本類物件的引用以及獲取本類唯一物件的靜態方法,當其他類呼叫這個靜態方法時,如果持有的本類物件的引用為null則建立一個本類物件並賦值給引用,否則直接返回引用物件。還有就是為了防止其他類通過new的方式建立物件,單例類需要將空的構造方法的定義為private。

懶漢式實現

下面實現是單例模式的基本實現,但是存線上程安全問題,不支援多執行緒

public class Singleton {

    private  static Singleton instance = null;//單例類提供的唯一物件引用

    //為了防止其他類通過 new Singleton() 建立類
    private Singleton(){}
    public static Singleton getInstance(){

        //在第一次獲取單例物件時,建立物件,
        //注意在多執行緒中會出現問題,可能會建立多個物件
        if(instance == null){
            instance = new Singleton();
        }
        return  instance;
    }
}

下面的實現是執行緒安全的,但是大部分時候其實是不需要同步的,所以效率低下

public class Singleton {

    private  static Singleton instance = null;//單例類提供的唯一物件引用

    //為了防止其他類通過 new Singleton() 建立類
    private Singleton(){}
    /**
     * 使用synchronized修飾靜態方法,實現執行緒同步
     * 注意synchronized 修飾 static 方法時 獲取的是類鎖(即Class本身)
     */
    public synchronized static Singleton getInstance(){
        //在第一次獲取單例物件時,建立物件,
        if(instance == null){
            instance = new Singleton();
        }
        return  instance;
    }
}

可以使用雙重檢驗實現多執行緒下的高效率,下面實現可以大大提高效率,也可以解決執行緒安全問題

public class Singleton {

    private  static Singleton instance = null;//單例類提供的唯一物件引用

    //為了防止其他類通過 new Singleton() 建立類
    private Singleton(){}
    public  static Singleton getInstance(){
        //在第一次獲取單例物件時,建立物件,
        //第一次檢查的目的是當instance 不為null時直接返回instance
        if(instance == null){
            //加鎖實現同步,防止建立多個物件
            synchronized (Singleton.class){
                /**
                 * 第二次檢查的目的,當系統開始執行,可能會出現很多執行緒同時呼叫這個方法,
                 * 所以一開始可能會有多個執行緒在鎖池中等待獲取物件鎖,
                 * 所以一開始可能會有多個執行緒可以執行到synchronized 程式碼塊中,這樣需要防止多次建立對像
                 */
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return  instance;
    }
}

餓漢式實現

餓漢式實現因為沒有鎖,所以執行效率會大大提高。但是類在載入時就初始化,沒有實現需要時在初始化,可能會浪費記憶體。

public class Singleton {

    //餓漢式是在類載入時就初始化,實現了執行緒安全,單容易浪費記憶體
    private  static Singleton instance = new Singleton();//單例類提供的唯一物件引用

    //為了防止其他類通過 new Singleton() 建立類
    private Singleton(){}
    public  static Singleton getInstance(){
      return  instance;
    }
}

以上是單例模式常見的實現方法,其他的實現方法還有如:靜態內部類的實現方法以及列舉的實現方法等,在設計單例模式時要注意如果需要在多執行緒情景下執行則需要實現執行緒安全。
對於多執行緒的知識可以檢視這篇部落格 [置頂] Java多執行緒學習(吐血超詳細總結)

相關文章