1. 程式人生 > 其它 >Java設計模式之單例模式

Java設計模式之單例模式

所謂類的單例設計模式,就是採取一定的方法保證在整個軟體系統中,對於某個類只能存在一個物件例項,並且該類只提供一個取得其物件例項的方法。

單例模式有8種

餓漢式(靜態常量)

JDK中,java.lang.Runtime原始碼就是採用這種單例模式。

class Singleton{

    // 1.構造器私有化(防止外部 new物件)
    private Singleton(){

    }
    // 2.類的內部建立物件
    private final static Singleton instance = new Singleton();
    // 3.向外暴露一個靜態的公共方法。getInstance
    public static Singleton getInstance(){
        return instance;
    }
}

優缺點:

  1. 優點:寫法簡單,在類裝載的時候就完成例項化,避免了執行緒同步的問題。
  2. 缺點:在類裝載的時候就完成例項化,沒有達到Lazy Loading的效果。如果從未使用過這個例項,則會造成記憶體浪費。

餓漢式(靜態程式碼塊)

class Singleton2{
    // 1.構造器私有化(防止外部 new物件)
    private Singleton2(){

    }
    // 2.類的內部建立物件
    private static Singleton2 instance;
    static {
        instance = new Singleton2();
    }
    // 3.向外暴露一個靜態的公共方法。getInstance
    public static Singleton2 getInstance(){
        return instance;
    }
}

優缺點同靜態常量。

懶漢式(執行緒不安全)

class Singleton3{
    private static Singleton3 instance;

    private Singleton3(){

    }

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

優缺點:

  1. 起到了懶載入的效果,但是隻能在單執行緒下使用。
  2. 如果在多執行緒下,一個執行緒進入了if(instance == null)判斷語句塊,還未來得及往下執行,另一個執行緒也通過了這個判斷語句,這時便會產生多個例項。所以在多執行緒環境下不可使用這種方式。

懶漢式(執行緒安全,同步方法)

class Singleton4{
    private static Singleton4 instance;

    private Singleton4(){

    }

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

優缺點:

  1. 解決了執行緒不安全的問題
  2. 效率太低,每個執行緒想獲得類的例項時,執行getInstance()方法都要進行同步。而其實這個方法只執行一次例項化程式碼就夠了,後面的想獲得該類例項直接return就行了。方法進行同步效率太低。

懶漢式(同步程式碼塊)

錯誤寫法,不展示。

雙重檢查

class Singleton6{

    private static volatile Singleton6 instance;

    private Singleton6(){}

    //提供一個靜態的公有方法,加入雙重檢查程式碼,解決執行緒安全問題,同時解決懶載入問題。
    public static Singleton6 getInstance(){
        if (instance == null){
            synchronized (Singleton6.class){
                if (instance == null){
                    instance = new Singleton6();
                }
            }
        }
        return instance;
    }
}

優缺點:

  1. Double-Check概念是多執行緒開發中常使用到的,如程式碼中所示,我們進行了兩次if(instance == null)檢查,這樣就可以保證執行緒安全了。
  2. 執行緒安全,懶載入,效率較高。

靜態內部類

class Singleton7 {

    private Singleton7(){}

    //靜態內部類,該類中有一個靜態屬性Singleton7
    //靜態內部類呼叫時才會裝載,JVM裝載是執行緒安全的過程。
    private static class SingletonInstance{
        private static final Singleton7 instance = new Singleton7();
    }
    
    public static Singleton7 getInstance(){
        return SingletonInstance.instance;
    }
}

優缺點:

  1. 採用了類裝載機制來保證初始化例項時只有一個執行緒。
  2. 靜態內部類方式在Singleton7類被裝載時,並不會立即例項化,而是在需要例項化時呼叫getInstance()才會裝載SingletonInstance類,從而完成Singleton7的例項化。
  3. 類的靜態屬性只會在第一次載入類的時候初始化,JVM保證了執行緒的安全性。
  4. 執行緒安全,懶載入,效率高。

列舉

enum Singleton8 {
    INSTANCE;
    public void sayOK(){
        System.out.println("OK");
    }
}

public class Singleton8Demo{
    public static void main(String[] args){
        Singleton8 instance = Singleton8.INSTANCE;
        Singleton8 instance2 = Singleton8.INSTANCE;
        System.out.println(instance == instance2);
    }
}

優缺點:

藉助JDK1.5中新增的列舉類來實現單例模式,不僅能避免多執行緒同步問題,而且還能防止反序列化重新建立新的物件,防止反射,推薦使用。