<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【原】從頭學習設計模式(一)——單例模式

       

      一、引入

        單例模式作為23種設計模式中的最基礎的一種模式,在平時開發中應用也非常普遍。到底哪些類應該設計成單例的呢,我們來舉個最通俗的例子。在一個父容器中單擊某個菜單項打開一個子窗口,如果不使用單例又沒有作菜單項的可用控制的話,每次單擊菜單項都會打開一個新窗口。這不僅會浪費內存資源,在程序邏輯上也是不可以接受的。

      二、最簡單的單例

        下面來看一個最簡單的單例模式的構造形式

          public class Program
          {
              private static void Main(string[] args)
              {
      
                  GetInstance();
                  Console.ReadLine();
              }
      
              private void GetInstance()
              {
                  Singleton objectSingleton = Singleton.getInstance();
              }
          }
      
          public class Singleton
          {
              private static Singleton instance = null;
              private Singleton()
              {
              }
      
              public static Singleton getInstance()
              {
                  if (instance == null)
                  {
                      instance = new Singleton();
                      Console.WriteLine("Create a singleton instance!");
                  }
                  return instance;
              }
          }

       

        這里通過幾個關鍵的地方以保證返回唯一的實例:

      1. 私有的構造器,防止客戶端用new關鍵字去創建實例對象
      2. 靜態的instance對象,保證全局唯一性
      3. 對外的公共的靜態實例方法,從類級別直接可調用此方法
      4. 通過判斷null值,決定是創建新實例還是直接返回。

       

      三、并發下的單例

        不過,以上標準的單例構造模式在多并發的情況下就有可能失效,請參考下面的這種情況。

       

              private static void Main(string[] args)
              {
                  //開啟10個線程來模擬多并發的情況
                  for (int i = 0; i < 10; i++)
                  {
                      Thread thread = new Thread(new ThreadStart(GetInstance));
                      thread.Start();
                  }
                  Console.ReadLine();
              }
      
              private static void GetInstance()
              {
                  Singleton objectSingleton = Singleton.getInstance();
              }
          }
      
          public class Singleton
          {
              private static Singleton instance = null;
              private Singleton()
              {
              }
      
              public static Singleton getInstance()
              {
                  //讓線程睡一會,來模擬有多個進程都已經在調用getInstance方法
                  Thread.Sleep(10);
                  if (instance == null)
                  {
                      instance = new Singleton();
                      Console.WriteLine("Create a singleton instance!");
                  }
                  return instance;
              }
          }

       

        以上的程序中開啟了10個線程,來模擬多個用戶同時訪問getInstance方法。在getInstance方法里,開始先讓線程睡一會,以模擬多個線程都已經進入了該方法。從運行的結果看上,基本上不能保證實例化唯一的實例了。

       

        產生這種問題的原因就是,當一個線程進入getInstance 方法,通過了 instance==null 的條件,還沒有來的及執行 instance = new Singleton() 時,另一個線程也通過了條件判斷,這時就會 new Singleton() 多次了。

        解決的辦法就是加鎖,只讓一個線程進來,參考以下代碼:

       

          public class Program
          {
              private static void Main(string[] args)
              {
                  //開啟100個線程來模擬多并發的情況
                  for (int i = 0; i < 100; i++)
                  {
                      Thread thread = new Thread(new ThreadStart(GetInstance));
                      thread.Start();
                  }
                  Console.ReadLine();
              }
      
              private static void GetInstance()
              {
                  Singleton objectSingleton = Singleton.getInstance();
              }
          }
      
          public class Singleton
          {
              private static Singleton instance = null;
              private static readonly object objForLock=new object();
              private Singleton()
              {
              }
      
              public static Singleton getInstance()
              {
                  //讓線程睡一會,來模擬有多個進程都已經在調用getInstance方法
                  Thread.Sleep(10);
                  //加一道鎖只讓一個線程進來
                  lock (objForLock)
                  {
                      if (instance == null)
                      {
                          instance = new Singleton();
                          Console.WriteLine("Create a singleton instance!");
                      }
                  }
                  return instance;
              }
          }

       

        這樣差不多可以達到我們的要求,只有一個實例對象存在可以保證了,但是這樣會帶來一點性能問題。如果每個線程進入getInstance方法后,都要lock一下以進行線程同步的話,每個線程到這里都要等待解鎖后才能進入,但是如果 instance已經不是null了,那就應該直接返回而不是等待解鎖,所以這里需要引入雙重鎖的單例構造方法,代碼如下:

              private static void Main(string[] args)
              {
                  //開啟100個線程來模擬多并發的情況
                  for (int i = 0; i < 100; i++)
                  {
                      Thread thread = new Thread(new ThreadStart(GetInstance));
                      thread.Start();
                  }
                  Console.ReadLine();
              }
      
              private static void GetInstance()
              {
                  Singleton objectSingleton = Singleton.getInstance();
              }
          }
      
          public class Singleton
          {
              private static Singleton instance = null;
              private static readonly object objForLock=new object();
              private Singleton()
              {
              }
      
              public static Singleton getInstance()
              {
                  //讓線程睡一會,來模擬有多個進程都已經在調用getInstance方法
                  Thread.Sleep(10);
                  //先判斷是不是已經實例化過了,避免進入鎖等待狀態
                  if(instance ==null)
                  {
                      //加一道鎖只讓一個線程進來
                      lock (objForLock)
                      {
                          if (instance == null)
                          {
                              instance = new Singleton();
                              Console.WriteLine("Create a singleton instance!");
                          }
                      }
                  }
      
                  return instance;
              }
          }

       

      四、“懶漢式”單例與“餓漢式”單例的比較

        所謂的“懶漢式”與“餓漢式”,就是實例對象的初始化時間不同:

        1. 在需要實例化的時候才進行實例化,就是懶漢式。我們上面的這些例子都是懶漢式的。懶漢式有好處當然是節省資源啦,需要的時候才去構造,平時不用占用內存。不過,這會帶來上面提到的在多并發下需要加鎖限制訪問的問題。

        2.類加載時就直接進行實例化,就是餓漢式。例如下面的代碼:

          private static Singleton instance = new Singleton();
          
          private Singleton() {
              
          }
          
          public static Singleton getInstance() {
              return instance;
          }

        餓漢式單例是當類第一次被加載時就會將instance進行實例化,這樣作的好處是不會帶來多并發下的線程安全問題了,也不用考慮鎖了。但反過來帶來的就是性能問題了,因為不管你需不需要將這個實例對象創建出來,它都已經被創建出來常駐內存了。所以如果是一個工廠模式、緩存了很多實例、那么就得考慮效率問題,因為這個類一加載則把所有實例不管用不用一塊創建。
        這里只是對兩種構造模式作了一個簡單的對比,實際項目中要應用哪種模式還是要看具體需求而定。

        

      posted @ 2013-10-24 12:49  Tony Zhao  閱讀(3327)  評論(13)    收藏  舉報
      主站蜘蛛池模板: 日韩区二区三区中文字幕| 亚洲av永久无码精品水牛影视 | 亚洲国产中文在线有精品| 久久精品国产亚洲av成人| 亚洲中文日韩一区二区三区| 河东区| 亚洲人成日韩中文字幕不卡| 一本精品99久久精品77| 少妇高潮惨叫喷水在线观看| 无遮挡高潮国产免费观看| 亚洲国产精品综合久久网各| 亚洲老熟女一区二区三区| 国产精品中文字幕在线| 国产熟睡乱子伦视频在线播放| 自偷自拍亚洲综合精品| 一区二区三区精品偷拍| 亚洲av色香蕉一区二区| 免费午夜无码片在线观看影院| 免费人妻无码不卡中文字幕系| 综合久久av一区二区三区| 四虎永久免费精品视频| 丁香花在线影院观看在线播放| 国产福利酱国产一区二区| 自拍第一区视频在线观看| 色视频在线观看免费视频| 中文字幕久久精品波多野结| 国产一国产看免费高清片| 97久久久亚洲综合久久| 亚洲 成人 无码 在线观看| 老色批国产在线观看精品| 国产av一区二区三区| 精品国产综合成人亚洲区| 亚洲人成电影网站色mp4| 77777亚洲午夜久久多人| 亚洲第一成人网站| 成人午夜大片免费看爽爽爽| 略阳县| 18岁日韩内射颜射午夜久久成人| 亚洲视频欧美不卡| 欧美大bbbb流白水| 国产精品一区二区三区卡|