設計模式三、單例模式

設計模式part3

單例模式

單例模式是一種常用的軟件設計模式。在它的核心結構中只包含一個被稱爲單例的特殊類。通過單例模式可以保證系統中一個類只有一個實例

常見的單例模式可以分爲懶漢模式和餓漢模式

懶漢模式

懶漢模式是指在第一次調用的時候進行實例化

【java】

publicclass Singleton1 {

    //私有的構造器可以在其他類中實例化被實例化

    private Singleton1(){}

    privatestatic Singleton1 singleton1 = null;

    publicstatic Singleton1 getInstance(){

        //第一次調用的時候實例化

        if(singleton1==null){

            singleton1 = new Singleton1();

        }

        returnsingleton1;

    }

}


然而這種方式會存在線程安全的問題,在多線程併發的情況下會出現問題,於是可以有一下方式進行優化

一、【java

publicstaticsynchronized Singleton1 getInstance(){

        //第一次調用的時候實例化

        if(singleton1==null){

            singleton1 = new Singleton1();

        }

        returnsingleton1;

}


synchronized關鍵字鎖住的是這個對象,這樣的用法,在性能上會有所下降,因爲每次調用getInstance(),都要對對象上鎖,事實上,只有在第一次創建對象的時候需要加鎖,之後就不需要了,所以,這個地方需要改進。我們改成下面這個:

二、【java

publicstatic Singleton1 getInstance() {

        if (singleton1 == null) {

            synchronized (singleton1) {

                if (singleton1 == null) {

                   singleton1 = new Singleton1();

                }

            }

        }

        returnsingleton1;

}


似乎解決了之前提到的問題,將synchronized關鍵字加在了內部,也就是說當調用的時候是不需要加鎖的,只有在instance爲null,並創建對象的時候才需要加鎖,性能有一定的提升。但是,這樣的情況,還是有可能有問題的,看下面的情況:在Java指令中創建對象和賦值操作是分開進行的,也就是說instance= new Singleton();語句是分兩步執行的。但是JVM並不保證這兩個操作的先後順序,也就是說有可能JVM會爲新的Singleton實例分配空間,然後直接賦值給instance成員,然後再去初始化這個Singleton實例。這樣就可能出錯了

publicclass Singleton2 {

    privatestaticclass SingletonFactory {   

        privatestaticfinal Singleton2 INSTANCE = new Singleton2();   

     }   

     private Singleton2 (){}   

     publicstaticfinal Singleton2 getInstance(){   

        return SingletonFactory.INSTANCE;   

     } 

}


使用靜態內部類的方式既實現了線程安全,又避免了同步帶來的性能影響。

 

餓漢模式

餓漢模式是指類初始化的時候就已經自行實例化了,天生就是線程安全的,不需要考慮線程安全的問題

publicclass Singleton3 {

    private Singleton3(){}

    privatestatic Singleton3 singleton3 = new Singleton3();

    publicstatic Singleton3 getInstance(){

        returnsingleton3;

    }

}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章