<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                四個不同單例模式寫法的Java源代碼 - 懶漢模式 - 餓漢模式 - 懶漢模式 + 安全線程 - 雙重檢驗鎖 第一個懶漢模式線程不安全,后三個都是線程安全的。四者的共有特點,也是單例模式的最主要特點,是其**構造函數是私有的**。還有一個特點是,有一個**靜態**的getInstance() 方法,靜態方法就是類方法。 # 懶漢模式 這個寫法是GoF提出單例模式時候給出的例子,影響力大,寫法簡單。 ~~~ package singleton; // 懶漢模式 public class SingletonLazy { private static SingletonLazy uniqueInstance; private SingletonLazy(){} // 私有的構造函數 public static SingletonLazy getInstance() { if(uniqueInstance == null) { uniqueInstance = new SingletonLazy(); } return uniqueInstance; } public String toString() { return "A simple way to apply Singleton, but is not thread safe"; } } ~~~ 然而問題在于:當有多于一個線程的時候,懶漢模式可能失效。舉個例子: 1. 線程A和線程B,相隔0.1納秒分別執行getInstance()方法,A先于B 1. 時刻”T 納秒”, A發現 uniqueInstance==null,準備開始new SingletonLazy( ) 1. 時刻”T+0.1 納秒”, **A還沒來得及new完SingletonLazy對象**,**此時B發現 uniqueInstance==null**,也準備開始new SingletonLazy( ) 1. 時刻”T+0.5 納秒”, A成功new完了SingletonLazy對象,uniqueInstance!=null 1. 時刻”T+0.6 納秒”, B成功new完了SingletonLazy對象 可以看出A,B兩個線程都new了SingletonLazy對象,懶漢模式失效。原因在于:A和B兩個線程相隔非常非常短的時間分別執行getInstance(),而且new SingletonLazy對象這個過程需要花費一定的時間。 # 餓漢模式 餓漢模式寫法,是一上來(類加載的時候)就給你實例一個Singleton對象,不管你此時需不需要。回顧一下懶漢模式寫法,你一開始不需要Singleton對象,然后程序運行到某一時刻,第一次調用getInstance()方法,才實例一個Singleton對象。餓漢模式的寫法,由JVM保證是安全的(雖然內部機制我不懂,我才剛開始學Java),不過簡單想一想,Singleton類加載之前,肯定不會有線程new Singleton(),此時Singleton()的構造函數還不存在呢~ 可以這么說,餓漢模式解決線程安全問題的方法是:從根子上回避這個問題。想法很好,寫法很簡單,不過呢要多花費一些空間(犧牲空間,換取時間,這個世界就是很難有兩全其美的事情) ~~~ package singleton; // 餓漢模式 public class SingletonEager { private static SingletonEager uniqueInstance = new SingletonEager(); // 在這里 new private SingletonEager(){} // 私有的構造函數 public static SingletonEager getInstance() { return uniqueInstance; } public String toString() { return "Create the unique instance when the class is loaded, which is thread safe"; } } ~~~ # 懶漢模式(線程安全) 在懶漢模式的基礎上,在getInstance() 方法的聲明中,增加關鍵詞synchronized,就可以實現線程安全了。畢竟同步嘛,線程A和B即使時間相隔非常非常短,比如相隔0.1納秒,那也是分先后呀。就因為A快上0.1納秒,所以就”捷足先登“了,拿到了鎖!B在0.1納秒后,發現getInstance()方法上了鎖,進不去了。 ~~~ package singleton; public class SingletonThreadSafe { private static SingletonThreadSafe uniqueInstance; private SingletonThreadSafe(){} // 私有的構造函數 // 這里同步了 public static synchronized SingletonThreadSafe getInstance() { if(uniqueInstance == null) { uniqueInstance = new SingletonThreadSafe(); } return uniqueInstance; } public String toString() { return "The getInstance() method is declared with keyword 'synchronized'," + " which is thread safe, but with low performance"; } } ~~~ 不過《Head First Design Pattern》說:Just keep in mind that synchronizing a method can decrease performance by a factor of 100。相差100倍,這對于程序性能的影響是相當的大呀! # 雙重檢驗鎖 這個是上面的synchronized方法的升級版本。仔細想一想,只有在第一次getInstance()的時候,才需要new singleton對象,對吧?如果不是第一次getInstance(),那就說明singleton對象已經存在了~于是有了下面的優化代碼 ~~~ package singleton; // double checked locking public class SingletonDCL { // 注意這個關鍵詞 private volatile static SingletonDCL uniqueInstance; private SingletonDCL(){} // 私有的構造函數 public static SingletonDCL getInstance() { if(uniqueInstance == null) // check once { synchronized(SingletonDCL.class) { if(uniqueInstance == null) // check twice { uniqueInstance = new SingletonDCL(); } } } return uniqueInstance; } public String toString() { return "A thread safe way to apply Singleton with good performance"; } } ~~~ synchronized的不是一個方法,而是一個方法里面的一個代碼塊,這樣被synchronized的部分減少了。 - 注意1:synchronized前后分別check兩次。第一個check,Singleton是否曾經被實例化過;第二個check,就相當于上一個例子”懶漢模式+線程安全“中的check - 注意2:volatile關鍵詞,這涉及到JVM內部的機制,先強行記住就行了。 # 測試及補充 ~~~ package singleton; public class Main { public static void main(String[] args) { SingletonLazy singletonLazy = SingletonLazy.getInstance(); SingletonLazy singletonLazy2 = SingletonLazy.getInstance(); System.out.println(singletonLazy); if(singletonLazy2.equals(singletonLazy)) { System.out.println("true"); // 同一個引用 } else { System.out.println("false"); } } } ~~~ 運行結果: ~~~ A simple way to apply Singleton, but is not thread safe true ~~~ **補充:** 《Head First Design Pattern》書中單例模式就這4種寫法。不過其實還有更多寫法,在實驗樓網站中,就還有靜態內部類寫法和枚舉類型寫法。《Head First Design Pattern》在GitHub的代碼中,有一個例子為了讓單例模式能夠派生出子類,把構造函數和靜態數據成員聲明為protected(子類訪問權限)。 深入單例模式以及其他設計模式,[猛戳這里(可以在新標簽頁中打開~)](http://blog.csdn.net/u013390476/article/details/50333763) [某大神博客,C++版本的單例模式,我覺得寫的不錯](http://blog.csdn.net/fu_zk/article/details/11892095) [這個鏈接好,C++博大精深。。。](http://segmentfault.com/q/1010000000593968)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看