日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

23种设计模式之《单例模式》

發布時間:2024/4/13 asp.net 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 23种设计模式之《单例模式》 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是單例模式

單例模式是23種設計模式中最簡單和易用的模式。在某些情境下,如在一個上市公司中,有很多不同級別的員工,但是公司的CEO或者CTO都是只有一個的,CEO或者CTO在公司里就要求是一個單例。單例模式,就是某個類因實際情況的需要,要求在全局的范圍內只能有唯一的實例對象,這個對象是常駐內存的,可以重復使用,降低重復創建對象的開銷。

單例模式的特點

  • 類的構造函數是私有的
  • 在類內部實例化對象,并通過靜態方法向外提供實例化的對象

下面主要講解實現單例模式的方法以及它們的優缺點

單例模式的實現

單例模式的目的,就是要確保在全局范圍內某個類的對象是唯一的。所以實現單例模式時,我們至少要考慮兩個影響對象創建的因素。

  • 在并發的環境下的線程安全
  • 反序列化

餓漢實現

在類第一次加載時,就進行對象的實例化。

public class SingletonDemo {private final static SingletonDemo mSingletonDemo = new SingletonDemo();private SingletonDemo() {}public static SingletonDemo getInstance() {return mSingletonDemo;}} 復制代碼

懶漢實現

在類加載時不進行對象的實例化,只在對象被第一次訪問時,才進行對象的實例化。

public class SingletonDemo {private static SingletonDemo mSingletonDemo;private SingletonDemo() {}public static SingletonDemo getInstance() {if(mSingletonDemo == null) {mSingletonDemo = new SingletonDemo();}return mSingletonDemo;}} 復制代碼

明顯,在多線程的環境下,上面兩種實現方式都不是線程安全的。為了實現線程安全,我們首先可以想到使用synchronized關鍵字。

線程安全的懶漢模式

public class SingletonDemo {private static SingletonDemo mSingletonDemo;private SingletonDemo() {}public static synchronized SingletonDemo getInstance() {if(mSingletonDemo == null) {mSingletonDemo = new SingletonDemo();}return mSingletonDemo;}} 復制代碼

關于synchronized關鍵字說明一下,synchronized聲明的靜態方法,同時只能被一個執行線程訪問,但是其他線程可以訪問這個對象的非靜態方法。即:兩個線程可以同時訪問一個對象的兩個不同的synchronized方法,其中一個是靜態方法,一個是非靜態方法。

所以,當有多個線程同時訪問getInstance靜態方法時,多個其他的線程只能等待,這時只有一個線程能夠訪問getInstance方法,等這個線程釋放后其他線程才能訪問。這樣就會影響速度和效率。

為了提高懶漢模式的速度和效率,可以減小鎖的粒度和次數。

雙重校驗鎖法

public class SingletonDemo {private static SingletonDemo mSingletonDemo;private SingletonDemo() {}public static synchronized SingletonDemo getInstance() {if(mSingletonDemo == null) {synchronized (SingletonDemo.class) {if(mSingletonDemo == null) {mSingletonDemo = new SingletonDemo();}}}return mSingletonDemo;}} 復制代碼

從上面可以看到,只有在第一次訪問時才會鎖定和創建類的對象,之后的訪問都是直接使用已經創建好的對象,這樣減少鎖定的次數和范圍,以達到提高單例模式的效率。

但是,對象的實例化,并不是一個原子性操作。即第11行代碼處,它可以分成下面三個步驟: 1、new SingletonDemo(),為SingletonDemo實例分配內存 2、調用SingletonDemo的構造器,完成初始化工作 3、將mSingletonDemo指向分配的內存空間

由于java處理器可以亂序執行,即無法保證2和3的執行順序。這對雙重校驗鎖法實現的單例模式有什么影響呢? 當第一個線程訪問getInstance方法時,會鎖定臨界區(第9行到第13行代碼),它實例化對象的順序是1=>3=>2,而在這時如果有第二個線程來訪問getInstance方法,由于第一個線程在處理器中執行完了3未執行2,第二個線程會馬上得到實例對象,因為第一個線程的3已經執行完即mSingletonDemo已經不為空。當第二個線程使用沒有初始化的對象時就會出現問題。

所以,雙重校驗鎖法也不是完美的,在并發環境下依然可能出現問題。

靜態內部類實現

public class SingletonDemo {private static SingletonDemo mSingletonDemo;private SingletonDemo() {}private static class SingletonHolder {private static final SingletonDemo INSTANCE = new SingletonDemo();}public static SingletonDemo getInstance() {return SingletonHolder.INSTANCE;}} 復制代碼

第一次加載SingletonDemo類時并不會實例化INSTANCE,只有在第一次調用getInstance方法時,才會加載SingletonHolder內部類,創建SingletonDemo實例。這種方式不僅確保了線程安全,也保證單例對象的唯一性,同時也實現了單例對象的懶加載。

枚舉實現

上面幾種實現方式,可能會因為反序列化而創建新的實例,所以必須重寫readResolve方法,在readResolve方法中返回已經創建的單例。

使用枚舉可以很簡單的實現單例模式,這也是Effective Java中提倡的方式。因為枚舉本身就是類型安全的,并且枚舉實例在任何情況下都是單例。

public enum SingletonEnumDemo {INSTANCE;public void justDoYourThing() {} } 復制代碼

枚舉單例使用

SingletonEnumDemo.INSTANCE.justDoYourThing(); 復制代碼

容器實現

public class SingletonDemo {private static Map<String, Object> singletonMap = new HashMap<String, Object>();private SingletonDemo() {}public static void registerService(String key, Object instance) {if (!singletonMap.containsKey(key)) {singletonMap.put(key, instance);}}public static Object getService(String key) {return singletonMap.get(key);}} 復制代碼

轉載于:https://juejin.im/post/5ac4458151882555867fa2ed

總結

以上是生活随笔為你收集整理的23种设计模式之《单例模式》的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。