Android中設計模式無處不在之單例模式

單例模式使用比較常見,用來保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。在Android application包中有個Bluetooth相關的包就用到了單例模式,實例代碼如下:

public class BluetoothOppManager {

    private static BluetoothOppManager INSTANCE;

/** Used when obtaining a reference to the singleton instance. */
    private static Object INSTANCE_LOCK = new Object();

/**
    * Get singleton instance.
    */
   public static BluetoothOppManager getInstance(Context context) {
       synchronized (INSTANCE_LOCK) {
           if (INSTANCE == null) {
               INSTANCE = new BluetoothOppManager();
           }
           INSTANCE.init(context);

           return INSTANCE;
       }
   }

}

這裏考慮到了多線程互斥的問題,引入了一個靜態只讀的進程輔助對象。它使得最先進入的那個線程來創建這個實例,以後的線程進入時不會創建實例對象。

不知道細心的讀者發現沒,這個getInstance()操作,每次被調用時,都會加上同步鎖,這樣會影響性能,所以有些改進的辦法,見下文:

public static BluetoothOppManager getInstance(Context context) {

       if(INSTANCE == null)
           synchronized (INSTANCE_LOCK) {
               if (INSTANCE == null) {
                   INSTANCE = new BluetoothOppManager();
               }
               INSTANCE.init(context);

          }

           return INSTANCE;
       }
   }

這種做法只有在實例未被創建的時候才加鎖,同時也能保證多線程的安全,所以該做法又叫Double-Check Locking(雙重鎖定)。這時又有同學要問,爲什麼我前面已經判斷了INSTANCE是否爲null,爲什麼同步代碼裏面又做了一次判斷?這個也不難理解,當INSTANCE爲null時,兩個線程同時調用,這時它們都可以通過第一輪判斷,都會立馬加鎖,但是最先進入臨界區的線程先加鎖,後進入的等待之。知道先進去的哥們創建好之後出來釋放爲止。此時,INSTANCE已經被創建,所以後進去的哥們被喚醒時,一看INSTANCE已經被創建了,那我就不創建了,所以也就避免了被創建兩次的尷尬。

最後附上單例模式的結構圖:

image

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