国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

單例模式的終極實(shí)現(xiàn)方案

Freelander / 800人閱讀

摘要:如此便可使得這一實(shí)現(xiàn)方式能夠同時(shí)具備線程安全延遲加載以及節(jié)省大量同步判斷資源等優(yōu)勢(shì),可以說(shuō)是單例模式的最佳實(shí)現(xiàn)了

單例模式(Singleton)是一種使用率非常高的設(shè)計(jì)模式,其主要目的在于保證某一類在運(yùn)行期間僅被創(chuàng)建一個(gè)實(shí)例,并為該實(shí)例提供了一個(gè)全局訪問(wèn)方法,通常命名為getInstance()方法。單例模式的本質(zhì)簡(jiǎn)言之即是:

控制實(shí)例數(shù)目

以Java為例,單例模式通常可分為餓漢式懶漢式兩種常規(guī)實(shí)現(xiàn)方式

餓漢式單例實(shí)現(xiàn)

餓漢式顧名思義,就是對(duì)類實(shí)例(食物?)的需求非常強(qiáng)烈,因此,在裝載該單例類的時(shí)候就會(huì)創(chuàng)建類實(shí)例。如下

public class Singleton {
    /**
     * 裝載時(shí)即創(chuàng)建類實(shí)例,并保存在類變量instance中
     * 加上static關(guān)鍵詞使得該變量能在getInstance()靜態(tài)方法中使用
     */
    private static Singleton instance = new Singleton();
 
    /**
     * 私有化構(gòu)造方法,使外部無(wú)法通過(guò)構(gòu)造方法構(gòu)造除instance外的類實(shí)例
     * 從而達(dá)到單例模式控制類實(shí)例數(shù)目的目的
     */
    private Singleton() {
    }
 
    /**
     * 類實(shí)例的全局訪問(wèn)方法
     * 加上static關(guān)鍵詞使得外部可以通過(guò)類名直接調(diào)用該方法獲取類實(shí)例
     * @return 單例類實(shí)例
     */
    public static Singleton getInstance() {
        //  由于類實(shí)例在類裝載時(shí)已被創(chuàng)建并保存在instance中,因此可直接返回
        return instance;
    }
}

事實(shí)上,在Android開(kāi)發(fā)中,Android Studio提供了一個(gè)直接創(chuàng)建單例類的功能(File->new->Singleton),該功能自動(dòng)生成的單例類正是采用了餓漢式的實(shí)現(xiàn)方式

懶漢式單例實(shí)現(xiàn)

說(shuō)到懶,我們自然而然會(huì)想到拖延癥這一惡習(xí),這一點(diǎn)和懶漢式的單例實(shí)現(xiàn)方式相似,這一實(shí)現(xiàn)方式會(huì)一直等到真正需要使用對(duì)象實(shí)例的時(shí)候再去創(chuàng)建該實(shí)例。如下

public class Singleton {
    /**
     * 裝載時(shí)不創(chuàng)建類實(shí)例,但需要利用一個(gè)類變量去保存后續(xù)創(chuàng)建的類實(shí)例
     * 添加static關(guān)鍵詞使得該變量能在getInstance()靜態(tài)方法中使用
     */
    private static Singleton instance = null;
 
    /**
     * 私有化構(gòu)造方法,使外部無(wú)法通過(guò)構(gòu)造方法構(gòu)造除instance外的類實(shí)例
     * 從而達(dá)到單例模式控制類實(shí)例數(shù)目的目的
     */
    private Singleton() {
    }
 
    /**
     * 類實(shí)例的全局訪問(wèn)方法
     * 添加static關(guān)鍵詞使得外部可以通過(guò)類名直接調(diào)用該方法獲取類實(shí)例
     * @return 單例類實(shí)例
     */
    public static Singleton getInstance() {
        //  如果instance未被初始化,則初始化該類實(shí)例
        if (instance == null) {
            instance = new Singleton();
        }
 
        return instance;
    }
}

事實(shí)上,雖然我們前面拿拖延癥來(lái)與懶漢式做類比,但懶漢式的拖延卻是實(shí)際開(kāi)發(fā)中的一種較為常見(jiàn)的節(jié)省資源的方式,即延遲加載思想。這一思想的核心在于直到需要使用某些資源或數(shù)據(jù)時(shí)再去加載該資源或獲取該數(shù)據(jù),這樣可以盡可能地節(jié)省使用前的內(nèi)存空間

線程安全的懶漢式單例實(shí)現(xiàn)

不難分析出,當(dāng)外部多個(gè)線程同時(shí)想要獲取單例類實(shí)例時(shí),上述懶漢式實(shí)現(xiàn)方式便很容易導(dǎo)致并發(fā)問(wèn)題。通常有如下幾種改進(jìn)方式

添加synchronized關(guān)鍵詞
....
public static synchronized Singleton getInstance() {
....

這種改進(jìn)方式是最簡(jiǎn)單的,但由于外部每次調(diào)用getInstance()方法時(shí)均需進(jìn)行判斷,因此該方式也是效率較低的

利用雙重檢查加鎖機(jī)制

雙重檢查加鎖機(jī)制分為如下兩重檢查

在程序每次調(diào)用getInstance()方法時(shí)先不進(jìn)行同步,而是在進(jìn)入該方法后再去檢查類實(shí)例是否存在,若不存在則進(jìn)入接下來(lái)的同步代碼塊

進(jìn)入同步代碼塊后將再次檢查類實(shí)例是否存在,若不存在則創(chuàng)建一個(gè)新的實(shí)例

這樣一來(lái),就只需要在類實(shí)例初始化時(shí)進(jìn)行一次同步判斷即可,而非每次調(diào)用getInstance()方法時(shí)都進(jìn)行同步判斷,大大節(jié)省了時(shí)間,具體實(shí)現(xiàn)如下

public class Singleton {
    /**
     * 裝載時(shí)不創(chuàng)建類實(shí)例,但需要利用一個(gè)類變量去保存后續(xù)創(chuàng)建的類實(shí)例
     * 添加volatile關(guān)鍵詞使其不會(huì)被本地線程緩存,保證線程能正確處理
     * 添加static關(guān)鍵詞使得該變量能在getInstance()靜態(tài)方法中使用
     */
    private volatile static Singleton instance = null;
 
    /**
     * 私有化構(gòu)造方法,使外部無(wú)法通過(guò)構(gòu)造方法構(gòu)造除instance外的類實(shí)例
     * 從而達(dá)到單例模式控制類實(shí)例數(shù)目的目的
     */
    private Singleton() {
    }
 
    /**
     * 類實(shí)例的全局訪問(wèn)方法
     * 添加static關(guān)鍵詞使得外部可以通過(guò)類名直接調(diào)用該方法獲取類實(shí)例
     * @return 單例類實(shí)例
     */
    public static Singleton getInstance() {
        //  第一重檢查:如果instance未被初始化,則進(jìn)入同步代碼塊
        if (instance == null) {
            //  同步代碼塊,保證線程安全
            synchronized (Singleton.class) {
                //  第二重檢查:如果instance未被初始化,則初始化該類實(shí)例
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
 
        return instance;
    }
}
利用Java緩存思想實(shí)現(xiàn)的單例實(shí)現(xiàn)
public class Singleton {
    //  類實(shí)例緩存KEY值
    private static final String KEY = "CACHE";
 
    //  類實(shí)例緩存容器
    private static Map map = new HashMap<>();
 
    /**
     * 私有化構(gòu)造方法,使外部無(wú)法通過(guò)構(gòu)造方法構(gòu)造除instance外的類實(shí)例
     * 從而達(dá)到單例模式控制類實(shí)例數(shù)目的目的
     */
    private Singleton() {
    }
 
    /**
     * 類實(shí)例的全局訪問(wèn)方法
     * 添加static關(guān)鍵詞使得外部可以通過(guò)類名直接調(diào)用該方法獲取類實(shí)例
     * @return 單例類實(shí)例
     */
    public static Singleton getInstance() {
        //  嘗試從緩存容器中獲取類實(shí)例
        Singleton instance = map.get(KEY);
        //  未能獲取類實(shí)例,則初始化該實(shí)例,并將其緩存至容器中
        if (instance == null) {
            instance = new Singleton();
            map.put(KEY, instance);
        }
 
        return instance;
    }
}

上述實(shí)現(xiàn)方式暫未考慮線程安全問(wèn)題。事實(shí)上,利用緩存來(lái)實(shí)現(xiàn)的單例模式其最大的優(yōu)點(diǎn)在于對(duì)單例模式進(jìn)行擴(kuò)展。我們自然而然地可以想到這么一種情況,既然在實(shí)際開(kāi)發(fā)中經(jīng)常需要保證某個(gè)類只能被創(chuàng)建一個(gè)實(shí)例,那么,會(huì)不會(huì)出現(xiàn)保證某個(gè)類只能被創(chuàng)建兩個(gè)或多個(gè)實(shí)例這種需求呢?對(duì)于這項(xiàng)需求,我們首先可以想到,上述實(shí)現(xiàn)方式中所建立的緩存容器是可以存儲(chǔ)多個(gè)類實(shí)例的,利用這一特點(diǎn),只需考慮一個(gè)問(wèn)題,即外部調(diào)用時(shí)到底需要為其返回哪一個(gè)實(shí)例,便可實(shí)現(xiàn)“雙例模式”以及“多例模式”(原諒我為它們?nèi)×艘恍┢婀值拿郑┝耍唧w實(shí)現(xiàn)如下

public class Singleton {
    //  可創(chuàng)建的最大類實(shí)例數(shù),這里以“雙例模式”為例
    private static final int MAX = 2;
 
    //  類實(shí)例緩存KEY值
    private static final String KEY = "CACHE";
 
    //  當(dāng)前正在使用的實(shí)例序號(hào)
    private static int index = 1;
 
    //  類實(shí)例緩存容器
    private static Map map = new HashMap<>();
 
    /**
     * 私有化構(gòu)造方法,使外部無(wú)法通過(guò)構(gòu)造方法構(gòu)造除instance外的類實(shí)例
     * 從而達(dá)到單例模式控制類實(shí)例數(shù)目的目的
     */
    private Singleton() {
    }
 
    /**
     * 類實(shí)例的全局訪問(wèn)方法
     * 添加static關(guān)鍵詞使得外部可以通過(guò)類名直接調(diào)用該方法獲取類實(shí)例
     * @return 單例類實(shí)例
     */
    public static Singleton getInstance() {
        //  嘗試從緩存容器中獲取第index個(gè)類實(shí)例
        String key = KEY + index;
        Singleton instance = map.get(key);
        //  未能獲取類實(shí)例,則初始化該實(shí)例,并將其緩存至容器相應(yīng)index中
        if (instance == null) {
            instance = new Singleton();
            map.put(key, instance);
        }
 
        //  這里以最基本的順序調(diào)用為例,其他復(fù)雜調(diào)度方式不加討論,具體調(diào)用方式如下
        //  index++,以在下一次調(diào)用中獲取下一個(gè)類實(shí)例,當(dāng)達(dá)到類實(shí)例數(shù)上限時(shí),重新獲取第一個(gè)類實(shí)例
        if ((++index) > MAX) {
            index = 1;
        }
 
        return instance;
    }
}
單例模式的最佳實(shí)現(xiàn)

綜合而言,上述實(shí)現(xiàn)方式都或多或少地存在諸如線程不安全、無(wú)法做到延遲加載等小缺陷。這里給出一個(gè)可以稱得上完美的最佳解決方案

Lazy Initialization Holder Class 模式

這一方案的核心在于Java的類級(jí)內(nèi)部類(即使用static關(guān)鍵詞修飾的內(nèi)部類,否則稱之為對(duì)象級(jí)內(nèi)部類)以及多線程缺省同步鎖,先來(lái)看看具體實(shí)現(xiàn)

public class Singleton {
    /**
     * 類級(jí)內(nèi)部類,用于緩存類實(shí)例
     * 該類將在被調(diào)用時(shí)才會(huì)被裝載,從而實(shí)現(xiàn)了延遲加載
     * 同時(shí)由于instance采用靜態(tài)初始化的方式,因此JVM能保證其線程安全性
     */
    private static class Instance {
        private static Singleton instance = new Singleton();
    }
 
    /**
     * 私有化構(gòu)造方法,使外部無(wú)法通過(guò)構(gòu)造方法構(gòu)造除instance外的類實(shí)例
     * 從而達(dá)到單例模式控制類實(shí)例數(shù)目的目的
     */
    private Singleton() {
    }
 
    /**
     * 類實(shí)例的全局訪問(wèn)方法
     * 添加static關(guān)鍵詞使得外部可以通過(guò)類名直接調(diào)用該方法獲取類實(shí)例
     * @return 單例類實(shí)例
     */
    public static Singleton getInstance() {
        return Instance.instance;
    }
}

在前面提到的餓漢式實(shí)現(xiàn)方式中,我們利用Java的靜態(tài)初始化、借由JVM實(shí)現(xiàn)了線程安全,因此這里同樣采用了這種方式。而另一方面,為了避免餓漢式實(shí)現(xiàn)中無(wú)法進(jìn)行延遲加載的缺陷,我們構(gòu)造了一個(gè)類級(jí)內(nèi)部類來(lái)緩存類實(shí)例,由于該類只會(huì)在通過(guò)getInstance()方法去調(diào)用時(shí)才會(huì)被系統(tǒng)裝載,換言之,只有初次調(diào)用getInstance()方法時(shí)才會(huì)去初始化類實(shí)例,因此也實(shí)現(xiàn)了延遲加載這一功能。如此便可使得這一實(shí)現(xiàn)方式能夠同時(shí)具備線程安全、延遲加載以及節(jié)省大量同步判斷資源等優(yōu)勢(shì),可以說(shuō)是單例模式的最佳實(shí)現(xiàn)了

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/67780.html

相關(guān)文章

  • 單例終極分析(一)

    摘要:好,看看大家喜聞樂(lè)見(jiàn)的并發(fā)場(chǎng)景下,這種簡(jiǎn)易的寫法會(huì)出現(xiàn)什么問(wèn)題兩個(gè)線程和同時(shí)訪問(wèn),它們都覺(jué)得判斷成立,分別執(zhí)行了步驟,成功創(chuàng)建出對(duì)象但是,我們通篇都在聊單例啊,和的玩法無(wú)疑很不單例問(wèn)題分析出來(lái)了,而解決上并不復(fù)雜讓線程同步就好。 單例的用處 如果你看過(guò)設(shè)計(jì)模式,肯定會(huì)知道單例模式,實(shí)際上這是我能默寫出代碼的第一個(gè)設(shè)計(jì)模式,雖然很長(zhǎng)一段時(shí)間我并不清楚單例具體是做什么用的。這里簡(jiǎn)單提一下單...

    Jenny_Tong 評(píng)論0 收藏0
  • 再遇設(shè)計(jì)模式之JavaScript篇

    摘要:在面向?qū)ο蟮恼Z(yǔ)言中,比如,等,單例模式通常是定義類時(shí)將構(gòu)造函數(shù)設(shè)為,保證對(duì)象不能在外部被出來(lái),同時(shí)給類定義一個(gè)靜態(tài)的方法,用來(lái)獲取或者創(chuàng)建這個(gè)唯一的實(shí)例。 萬(wàn)事開(kāi)頭難,作為正經(jīng)歷菜鳥賽季的前端player,已經(jīng)忘記第一次告訴自己要寫一些東西出來(lái)是多久以的事情了。。。如果,你也和我一樣,那就像我一樣,從現(xiàn)在開(kāi)始,從看到這篇文章開(kāi)始,打開(kāi)電腦,敲下你的第一篇文章(或者任何形式的文字)吧。 ...

    Clect 評(píng)論0 收藏0
  • 重寫GridView實(shí)現(xiàn)仿今日頭條頻道編輯頁(yè)(1)

    摘要:但由于這里僅僅是實(shí)現(xiàn)一個(gè),因此存儲(chǔ)功能僅通過(guò)一個(gè)單例類來(lái)模擬實(shí)現(xiàn)。 本文旨在通過(guò)重寫GridView,配合系統(tǒng)彈窗實(shí)現(xiàn)仿今日頭條的頻道編輯頁(yè)面 注:由于代碼稍長(zhǎng),本文僅列出關(guān)鍵部分,完整工程請(qǐng)參見(jiàn)【https://github.com/G9YH/YHChannelEdit】 在開(kāi)始講解盜版的實(shí)現(xiàn)方案前,讓我們先來(lái)看看正版與盜版的實(shí)際使用效果對(duì)比,首先是正版 showImg(https:...

    張憲坤 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<