Android開發設計模式之——單例模式關於線程不安全問題處理

來源:互聯網
上載者:User

標籤:

單例模式是設計模式中最常見也最簡單的一種設計模式,保證了在程式中只有一個執行個體存在並且能全域的訪問到。比如在Android實際APP 開發中用到的 帳號資訊對象管理, 資料庫物件(SQLiteOpenHelper)等都會用到單例模式。下面針對一些例子分析一下我們在開發過程中應用單例模式需要注意的點。


一、作用
單例模式(Singleton):保證一個類僅有一個執行個體,並提供一個訪問它的全域訪問點

二、適用情境

1. 應用中某個執行個體對象需要頻繁的被訪問。

2. 應用中每次啟動只會存在一個執行個體。如帳號系統,資料庫系統。

三、常用的使用方式

(1)懶漢式

這是在開發中很容易就能寫出來的一種方式,如下

[java] view plain copy  
  1. public class Singleton {  
  2.   
  3.     /* 持有私人靜態執行個體,防止被引用,此處賦值為null,目的是實現消極式載入 */  
  4.     private static Singleton instance = null;  
  5.   
  6.     /* 私人構造方法,防止被執行個體化 */  
  7.     private Singleton() {  
  8.     }  
  9.   
  10.     /* 1:懶漢式,靜態工程方法,建立執行個體 */  
  11.     public static Singleton getInstance() {  
  12.         if (instance == null) {  
  13.             instance = new Singleton();  
  14.         }  
  15.         return instance;  
  16.     }  
  17. }  

調用:

[java] view plain copy  
  1. Singleton.getInstance().method();  

優點:消極式載入(需要的時候才去載入)

缺點: 線程不安全,在多線程中很容易出現不同步的情況,如在資料庫物件進行的頻繁讀寫操作時。

(2)加同步鎖

既然線程不安全,那就加上同步鎖,一種加法如下:

[java] view plain copy  
  1. /*2.懶漢式變種,解決安全執行緒問題**/  
  2.  public static synchronized Singleton getInstance() {  
  3.      if (instance == null) {  
  4.          instance = new Singleton();  
  5.      }  
  6.      return instance;  
  7.  }  

更一般的寫法是這樣

[java] view plain copy  
  1. /*加上synchronized,但是每次調用執行個體時都會載入**/  
  2.  public static Singleton getInstance() {  
  3.      synchronized (Singleton.class) {  
  4.          if (instance == null) {  
  5.              instance = new Singleton();  
  6.          }  
  7.      }  
  8.      return instance;  
  9.  }  

調用:

[java] view plain copy  
  1. Singleton.getInstance().method();  

優點:解決了線程不安全的問題。

缺點:效率有點低,每次調用執行個體都要判斷同步鎖

補充:在Android源碼中使用的該單例方法有:InputMethodManager,AccessibilityManager等都是使用這種單例模式

(3)雙重檢驗鎖

要最佳化(2)中因為每次調用執行個體都要判斷同步鎖的問題,很多人都使用下面的一種雙重判斷校正的辦法

[java] view plain copy  
  1. /*3.雙重鎖定:只在第一次初始化的時候加上同步鎖*/  
  2.   public static Singleton getInstance() {  
  3.       if (instance == null) {  
  4.           synchronized (Singleton.class) {  
  5.               if (instance == null) {  
  6.                   instance = new Singleton();  
  7.               }  
  8.           }  
  9.       }  
  10.       return instance;  
  11.   }  

這種方法貌似很完美的解決了上述效率的問題,它或許在並發量不多,安全性不太高的情況能完美運行,但是,這種方法也有不幸的地方。問題就是出現在這句

[java] view plain copy  
  1. instance = new Singleton();  

在JVM編譯的過程中會出現指令重排的最佳化過程,這就會導致當 instance實際上還沒初始化,就可能被分配了記憶體空間,也就是說會出現 instance !=null 但是又沒初始化的情況,這樣就會導致返回的 instance 不完整(可以參考:http://www.360doc.com/content/11/0810/12/1542811_139352888.shtml)。

調用:

[java] view plain copy  
  1. Singleton.getInstance().method();  

優點:在並發量不多,安全性不高的情況下或許能很完美運行單例模式

缺點:不同平台編譯過程中可能會存在嚴重安全隱患。

補充:在android映像開源項目Android-Universal-Image-Loader (https://github.com/nostra13/Android-Universal-Image-Loader)中使用的是這種方式

(4)內部類的實現

內部類是一種好的實現方式,可以推薦使用一下:

[java] view plain copy  
  1. public class SingletonInner {  
  2.   
  3.     /** 
  4.      * 內部類實現單例模式 
  5.      * 消極式載入,減少記憶體開銷 
  6.      *  
  7.      * @author xuzhaohu 
  8.      *  
  9.      */  
  10.     private static class SingletonHolder {  
  11.         private static SingletonInner instance = new SingletonInner();  
  12.     }  
  13.   
  14.     /** 
  15.      * 私人的建構函式 
  16.      */  
  17.     private SingletonInner() {  
  18.   
  19.     }  
  20.   
  21.     public static SingletonInner getInstance() {  
  22.         return SingletonHolder.instance;  
  23.     }  
  24.   
  25.     protected void method() {  
  26.         System.out.println("SingletonInner");  
  27.     }  
  28. }  

調用:

[java] view plain copy  
  1. SingletonInner.getInstance().method();  

優點:消極式載入,安全執行緒(java中class載入時互斥的),也減少了記憶體消耗

(5)枚舉的方法

這是網上很多人推薦的一種做法,但是貌似使用的不廣泛,大家可以試試,

[java] view plain copy  
  1. /** 
  2.  * @function:單例模式枚舉實現 
  3.  * @author xuzhaohu 
  4.  *  
  5.  */  
  6. public enum SingletonEnum {  
  7.     /** 
  8.      * 1.從Java1.5開始支援; 
  9.      * 2.無償提供序列化機制; 
  10.      * 3.絕對防止多次執行個體化,即使在面對複雜的序列化或者反射攻擊的時候; 
  11.      */  
  12.   
  13.     instance;  
  14.   
  15.     private String others;  
  16.   
  17.     SingletonEnum() {  
  18.   
  19.     }  
  20.   
  21.     public void method() {  
  22.         System.out.println("SingletonEnum");  
  23.     }  
  24.   
  25.     public String getOthers() {  
  26.         return others;  
  27.     }  
  28.   
  29.     public void setOthers(String others) {  
  30.         this.others = others;  
  31.     }  
  32. }  

調用:

 

[java] view plain copy  
  1. SingletonEnum.instance.method();  

優缺點:如代碼中注釋。

 

上面主要講了單例模式5種建立方法,大家可以根據其優缺點進行個人實際項目中的使用。講的屬於拋磚引玉,大家多提意見。

Android開發設計模式之——單例模式關於線程不安全問題處理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.