設計模式之禪之單例模式!

單例模式:建立全局的惟一一個實例!安全

一、普通單例多線程

public class Singleton{性能

    private Singleton single =  null;優化

    private Singleton(){this

    }線程

    public Singleton getSingleton(){對象

        if(null ==single ){排序

             single = new Singleton();       get

         }同步

        return single;

    }

} 此方法,及其不安全

二、餓漢式

public class Singleton{

    private static Singleton single =  new Singleton(); 

    private Singleton(){

     }

    public Singleton getSingleton(){

        return single;

    }

} 此方式在類加載的時候就建立了單例對象,因爲類在加載的時候對其方法是沒有什麼影響和調用的,因此,設置一個公共方法直接返回實例!此方法是線程安全的,由於此類加載以後實例對象只初始化一次,而且有static修飾,也不會被GC回收,無論多少個線程調用,都只是一個實例!

三、懶漢式

public class Singleton{

    private static Singleton single =  null;

    private Singleton(){

    }

    public static Singleton getSingleton(){

        if(null ==single ){

             single = new Singleton();       

         }

        return single;

    }

}懶漢式只是在類加載的時候建立了一個引用,可是並無建立對象,只有在用到getSingleton方法的時候纔會去判斷爲null的時候去建立對象,在多線程狀況下此方法也是不安全的,有可能會建立多個對象的狀況!因此咱們對懶漢式進行改進 同步鎖的懶漢式

public class Singleton{

    private static Singleton single =  null;

    private Singleton(){

    }

    public static synchornized Singleton getSingleton(){

        if(null ==single ){

             single = new Singleton();       

         }

        return single;

    }

}咱們在方法上加上了同步鎖,此時單例是安全的,可是效率會降低,當一個線程進來的時候其餘的線程就只能在外面等待,並不能作其餘的事情,這就是阻塞是工做方式,因而咱們就又對其進行改進,讓他們先判斷再進來

public class Singleton{

    private static Singleton single =  null;

    private Singleton(){

    }

    public static Singleton getSingleton(){

        if(null ==single ){

            synchornized (this){

                   single = new Singleton();       

                    }

         }

        return single;

    }

}這個方法咱們優化了那些不是null的對象判斷,不是null的時候直接返回對象,不在浪費時間進同步鎖裏面了!可是這就會又出現問題,咱們的同步塊兒裏面的就又會出現問題,當兩個線程同時判斷是null的時候,這時候就可能建立兩個對象了!因此咱們就又對其改進,在同步塊兒裏面再進行一次判斷

public class Singleton{

    private static Singleton single =  null;

    private Singleton(){

    }

    public static Singleton getSingleton(){

        if(null ==single ){

            synchornized (this){

                 if(null ==single ){

                       single = new Singleton();

                  }       

              }

         }

        return single;

    }

}咱們對這個單例進行double check,雙檢查,這樣就會保證總會一個線程初始化了就不會在初始化對象了!可是這是對的嗎?不對的,虛擬機在建立對象的時候會進行重排序,進而是性能更加優異!因此 single = new Singleton();這個句子會發生重排序,咱們要用violate去修飾Singleton,具體的violate能夠去看看個人violate關鍵字的意思!因此就變成了這樣

public class Singleton{

    private violate static Singleton single =  null;

    private Singleton(){

    }

    public static Singleton getSingleton(){

        if(null ==single ){

            synchornized (this){

                 if(null ==single ){

                       single = new Singleton();

                  }       

              }

         }

        return single;

    }

}

(待續)

相關文章
相關標籤/搜索