<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    神奇好望角 The Magical Cape of Good Hope

    庸人不必自擾,智者何需千慮?
    posts - 26, comments - 50, trackbacks - 0, articles - 11
      BlogJava :: 首頁 ::  :: 聯(lián)系 :: 聚合  :: 管理

    單例模式的一個疑問

    Posted on 2012-01-10 17:39 蜀山兆孨龘 閱讀(1847) 評論(6)  編輯  收藏 所屬分類: Java SE

    網(wǎng)上很多關于單例模式寫法的文章,不外乎餓漢和懶漢兩種形式的討論。很多人喜歡用懶漢式,因為覺得它實現(xiàn)了延遲加載,可以讓系統(tǒng)的性能更好。但事實果真如此嗎?我對此存疑。

    首先我們檢查一下餓漢和懶漢單例模式最簡單的寫法(這里不討論哪種懶漢寫法更好):

    // 餓漢
    public final class HungrySingleton {
        private static final HungrySingleton INSTANCE = new HungrySingleton();
    
        private HungrySingleton() {
            System.out.println("Initializing...");
        }
    
        public static HungrySingleton getInstance() {
            return INSTANCE;
        }
    }
    
    // 懶漢
    public final class LazySingleton {
        private static LazySingleton INSTANCE;
    
        private LazySingleton() {
            System.out.println("Initializing...");
        }
    
        public static synchronized LazySingleton getInstance() {
            if (INSTANCE == null) {
                INSTANCE = new LazySingleton();
            }
            return INSTANCE;
        }
    }
        

    從理論上來說,HungrySingleton 的單例在該類第一次使用的時候創(chuàng)建,而 LazySingleton 的單例則在其 getInstance() 方法被調(diào)用的時候創(chuàng)建。至于網(wǎng)上有人聲稱“餓漢式不管用不用都會初始化”,純屬走路的時候步子邁得太大。誰的加載更遲?如果你只是調(diào)用它們的 getInstance() 方法來得到單例對象,則它們都是延遲加載,這樣懶漢式?jīng)]有任何意義,而且由于 LazySingleton 采取了同步措施,性能更低(可以說任何懶漢式的性能都低于餓漢式)。當你使用一個單例類的時候,難道第一步不是調(diào)用 getInstance() 么?所以在自己的代碼里,我更喜歡用餓漢式。

    下面用一個例子來測試加載順序:

    // 餓漢
    System.out.println("Before");
    HungrySingleton.getInstance();
    System.out.println("After");
    
    // 懶漢
    System.out.println("Before");
    LazySingleton.getInstance();
    System.out.println("After");
        

    輸出結果都是:

    Before
    Initializing...
    After

    那么,懶漢模式還有什么存在意義?如果系統(tǒng)使用了某些需要在啟動時對類進行掃描的框架,使用餓漢式的話,啟動時間比懶漢式更長,如果使用了大量單例類,不利于開發(fā)階段。在系統(tǒng)的正式運行階段,所有的單例類遲早都要加載的,總的說來兩者性能持平,但是懶漢式每次都至少多一個判斷,所以越到后期越體現(xiàn)餓漢的優(yōu)越性。

    最后,推薦下《Effective Java》第二版指出的用枚舉類型實現(xiàn)的餓漢單例模式:

    // 餓漢
    public enum HungrySingleton {
        INSTANCE;
    
        private HungrySingleton() {
        }
    }
    

    這種寫法不但最簡潔,還能輕易擴展為實例數(shù)量固定的“多例模式”。


    評論

    # re: 單例模式的一個疑問[未登錄]  回復  更多評論   

    2012-01-11 08:33 by test
    public enum HungrySingleton 不會延遲加載

    # re: 單例模式的一個疑問  回復  更多評論   

    2012-01-11 10:15 by 蜀山兆孨龘
    @test
    只有在第一次用 HungrySingleton 的時候才會加載其單例對象。如果代碼里面不使用這個枚舉,根本不會加載。這還不叫延遲加載?

    # re: 單例模式的一個疑問  回復  更多評論   

    2012-01-11 11:45 by Sakura
    enum是用了java的語法特性

    我們開發(fā)組用單例模式時,將實例緩存下來:
    private ModelLocator model = ModelLocator.getInstance();
    每次用時都直接用model,而不是重復的調(diào)用getInstance()
    保持這種用法約定的話就達到了Lazy的優(yōu)勢。
    對象只有第一次使用時才加載,加載后保存在private 成員變量中,
    以后每次用時不會再調(diào)用getInstance(),即不會參與多余的判斷和同步的性能消耗。
    如果不Lazy的話,采用框架啟動掃描類時會慢

    java的語法特性,完全可以用enum來實現(xiàn)非Lazy加載,代碼簡潔、可讀性高

    # re: 單例模式的一個疑問  回復  更多評論   

    2012-01-11 13:21 by 蜀山兆孨龘
    @Sakura
    你這種寫法確實達到了延遲的效果,但我并不覺得它有什么大的優(yōu)勢,除非在你的系統(tǒng)中有相當一部分單例類很難被調(diào)用——這幾乎不可能,早晚都會全部加載。

    系統(tǒng)的啟動時間長一點沒關系,在運行的時候時不時卡一下(延遲加載單例)就不太友好了。

    # re: 單例模式的一個疑問[未登錄]  回復  更多評論   

    2012-01-12 09:28 by test
    加載HungrySingleton類的時候就會實例化,這個不叫延遲加載
    加載類的時候不實例化而是真正用到實例的時候?qū)嵗沤醒舆t加載

    # re: 單例模式的一個疑問  回復  更多評論   

    2012-01-12 10:24 by 蜀山兆孨龘
    @test
    當你使用一個單例類的時候,第一步不是調(diào)用 getInstance() 嗎?莫非你還在單例類里面寫了不少靜態(tài)工具方法?當然,除非你正在做一個會對類進行掃描的框架。
    主站蜘蛛池模板: 女人被弄到高潮的免费视频| 在线视频精品免费| 亚洲一区二区三区无码影院| 亚洲欧美第一成人网站7777| 成人免费毛片内射美女APP | 内射少妇36P亚洲区| 你懂的免费在线观看网站| 久久香蕉国产线看观看亚洲片| 中文成人久久久久影院免费观看| 亚洲欧洲日产国码av系列天堂| 成人久久免费网站| 亚洲美女在线观看播放| 日韩吃奶摸下AA片免费观看| 亚洲AV无码一区二区大桥未久 | 污污网站免费观看| 亚洲欧洲国产经精品香蕉网| 成人毛片免费播放| 免费无码一区二区| 亚洲va无码专区国产乱码| 18成禁人视频免费网站| 国产精品亚洲精品| 亚洲第一视频在线观看免费| 国产午夜精品免费一区二区三区| 亚洲精品在线免费观看视频| 精品国产麻豆免费网站| 成年免费a级毛片免费看无码| 亚洲美女视频免费| 免费一看一级毛片人| a级日本高清免费看| 亚洲av无码片区一区二区三区| 精品国产一区二区三区免费看| caoporm超免费公开视频| 亚洲美女视频网站| 亚洲av再在线观看| 中文字幕在线观看免费视频| 亚洲精品人成网线在线播放va| 成人午夜亚洲精品无码网站| 一个人看的www在线观看免费 | 黄床大片30分钟免费看| 亚洲AV中文无码乱人伦下载| 成人片黄网站色大片免费|