天天看點

單例模式和雙重檢測的小結 1、餓漢模式 2、懶漢模式,延時加載

設計模式的經典模式之一——單例模式

這個也是面試經常被問起的面試,一般都要求手寫

【餓漢模式】非延時加載 ——以空間換時間

【懶漢模式】延時加載——以時間換空間

看似簡單,但是在懶漢模式還隐藏了一個雙重檢測,其中還是涉及到jvm記憶體的“無序寫入”問題(後面使用的 volatile )

比較簡單,非延時加載,一上來就把對象給new出來了

<span style="font-family:microsoft yahei;font-size:14px;">public class singleton {  

    private singleton(){} //預設構造器  

    private static singleton instance = new singleton();//直接加載  

    public singleton getintance(){  

        return instance;  

    }  

}</span>  

    private singleton() { } // 預設構造器  

    private static singleton instance = null;// 延時加載  

    //每次運作都要建立執行個體因而需要加鎖保護  

    public static synchronized singleton getintance() {  

        if (instance == null) {  

            instance = new singleton();// 判斷之後加載  

        }  

上面盡管這樣做到了線程安全,并且解決了多執行個體問題,但并不高效。在任何調用這個方法的時候,你都需要承受同步帶來的性能開銷,然而同步隻在第一次調用的時候才被需要,也就是單例類執行個體建立的時候。這将促使我們使用雙重檢查鎖模式(double checked locking pattern),一種隻在臨界區代碼加鎖的方法。一般稱其為雙重檢查鎖,因為會有兩次檢查 _instance == null,一次不加鎖,另一次在同步塊上加鎖。

    private volatile static singleton instance = null;// volatile 可見性/防止重排序  

    public static singleton getintance() {  

        // 第一重判斷  

            // 鎖定代碼塊  

            synchronized (singleton.class) {  

                // 第二重判斷  

                if (instance == null) {  

                    instance = new singleton();// 判斷之後加載  

                }  

            }  

如果使用雙重檢查鎖定來實作懶漢式單例類,需要在靜态成員變量instance之前增加修飾符volatile(可見性,防止重排序),被volatile修飾的成員變量可以確定多個線程都能夠正确處理,且該代碼隻能在jdk 1.5及以上版本中才能正确執行。

<span style="font-family:microsoft yahei;font-size:14px;">    public class singleton{    

      public static final threadlocal  threadinstance=new threadlocal();    

     public static singleton singleton=null;    

      public static getsingleton(){    

         if(threadinstance.get()==null){    

             createsingleton();    

          }    

      }    

      public static singleton createsingleton(){    

         synchronized(singleton.class){    

           if(singleton==null){    

                singleton=new singleton();    

            }    

    }   </span>  

threadlocal的全局變量局部化 第一次檢測采用線程局部來做如果線程已經通路過則不需要進入同步塊

轉載:http://blog.csdn.net/xsf50717/article/details/47305203