最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java單例模式中的餓漢和懶漢模式

 更新時(shí)間:2023年04月06日 14:28:14   作者:筑夢小子  
這篇文章主要介紹了詳解Java單例模式中的餓漢和懶漢模式,單例模式中有兩種模式一種是餓漢模式,一種是懶漢模式,那么他們有什么區(qū)別呢,需要的朋友可以參考下本文

一.什么是單例模式

保證某個(gè)類在程序中只存在一份實(shí)例,而不會創(chuàng)建多個(gè)實(shí)例,這樣就會提高效率。

在單利模式中一般只提供一個(gè)getInstance()方法來獲取實(shí)例對象,不提供setInstance()方法,目的是為了避免再實(shí)例化出其他實(shí)例對象。

其中單例模式中有兩種模式一種是餓漢模式,一種是懶漢模式。

一.餓漢模式

1.餓漢模式的概念

餓漢模式就是在類加載的時(shí)候立刻會實(shí)例化,后續(xù)使用就只會出現(xiàn)一份實(shí)例。

2.餓漢模式代碼

package thread.example;
//餓漢模式
public class HungrySingle {
//在類加載的時(shí)候就實(shí)例化了,類加載只有一次,所以值實(shí)例化出了一份該實(shí)例對象
    private static HungrySingle instance = new HungrySingle();
    public static HungrySingle getInstance() {
        return instance;
    }
}

3.多線程是否線程安全

在類加載的時(shí)候就已經(jīng)實(shí)例化了,所以該實(shí)例化沒有涉及到實(shí)例化的修改操作,只是進(jìn)行讀取操作。在多線程情況下是線程安全的。 

二.懶漢模式

1.懶漢模式的概念

在類加載的時(shí)候沒有直接實(shí)例化,而是調(diào)用指定實(shí)例方法的時(shí)候再進(jìn)行實(shí)例化,這樣就能保證不想使用的時(shí)候也不會實(shí)例化。一般來說比餓漢模式的效率高。

2.單線程情況下的懶漢模式

package thread.example;
//單線程的懶漢模式
public class LazySingle {
    private static LazySingle instance = null;
    //只有在調(diào)用該方法的時(shí)候才實(shí)例化
    public static LazySingle getInstance() {
        if(instance == null) {
            instance = new LazySingle();
        }
        return instance;
    }
}

3.多線程情況下的懶漢模式

(1)導(dǎo)致懶漢模式在多線程情況下的不安全原因

在多線程的情況下,由于可能兩個(gè)線程都會得到一份instance=null,這是因?yàn)槿绻€程1修改了自己縣城中的instance后還沒來得及修改主內(nèi)存中的instance,所導(dǎo)致線程2也實(shí)例化出了一份instance對象,這時(shí)候也就不再是單例模式了。主要導(dǎo)致該問題的是由于這里面涉及到了對instance的修改操作,失去了原子性,為了保證原子性,我們想到了加鎖,從而實(shí)現(xiàn)線程安全問題。

(2)解決方法代碼示例

版本1

package thread.example;
//多線程安全下的懶漢模式
    public class LazySingle {
        private LazySingle() {
    }
    private static LazySingle instance = null;
    //只有在調(diào)用該方法的時(shí)候才實(shí)例化
    public static synchronized LazySingle getInstance() {
        if (instance == null) {
            instance = new LazySingle();
        }
        return instance;
    }
}

版本1的代碼雖然保證了線程安全,但是每次調(diào)用該方法時(shí)還是會出現(xiàn)加鎖解鎖問題,為了進(jìn)一步優(yōu)化,我們可以減小鎖的粒度來提高效率,因?yàn)榧恿随i之后也就和高并發(fā)無緣了,但我們還是想提高效率,所以才會進(jìn)行優(yōu)化。

版本2

雙重if判斷加鎖提高效率

package thread.example;
 
public class SecurityLazyModle {
    private LazySingle() {
    }
    private static volatile SecurityLazyModle instance = null;//保證內(nèi)存可見性,防止編譯器過度優(yōu)化(指令重排序)
    public static SecurityLazyModle getInstance() {
        if(instance == null) {
            synchronized (SecurityLazyModle.class) {
                if(instance == null) {
                    instance = new SecurityLazyModle();
                }
            }
        }
        return instance;
    }
}

版本2的解釋說明

第一層if是為了判斷當(dāng)前是否已經(jīng)把實(shí)例創(chuàng)建出來,第二層synchronized是為了使進(jìn)入當(dāng)前if中的線程來競爭鎖,當(dāng)拿到鎖的線程進(jìn)入到第三層if之后判斷是否為空,不為空就是實(shí)例化對象,然后再釋放鎖,釋放鎖之后,instance已經(jīng)不為空了,后面的線程就被阻擋在了第三層if這里了,之后再來訪問getInstance()方法,發(fā)現(xiàn)該instance已經(jīng)不為空了,也就不用再搶占鎖資源了,因?yàn)楦偁庢i也消耗大量的時(shí)間。通過這樣處理,既保證了線程安全,也提高了效率。

這里使用volatile是為了防止編譯器優(yōu)化導(dǎo)致的指令重排序,在進(jìn)行new一個(gè)對象不是原子性操作,可以分為三步驟:

  1. 1.分配內(nèi)存空間
  2. 2.實(shí)例化對象
  3. 3.給變量賦值

對于上面的執(zhí)行,如果1和3先執(zhí)行了(假設(shè)2還沒有完成),在第一層if外的線程這時(shí)候判斷不為null,這時(shí)候就會直接返回該對象,但是這個(gè)對象只執(zhí)行了一半,之后使用就會導(dǎo)致線程安全問題。

通過volatile就可以確保這3步驟必須執(zhí)行完(無論順序如何,最終都會執(zhí)行完),外面的線程才可以執(zhí)行,這時(shí)候就保證了該對象的完整性。

到此這篇關(guān)于詳解Java單例模式中的餓漢和懶漢模式的文章就介紹到這了,更多相關(guān)Java單例模式餓漢懶漢模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • OpenFeign調(diào)用服務(wù)請求頭丟失Token的解決

    OpenFeign調(diào)用服務(wù)請求頭丟失Token的解決

    這篇文章主要介紹了OpenFeign調(diào)用服務(wù)請求頭丟失Token的解決方法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Redis?+?Java攔截器實(shí)現(xiàn)用戶匿名和非匿名訪問

    Redis?+?Java攔截器實(shí)現(xiàn)用戶匿名和非匿名訪問

    本文主要介紹了Redis?+?Java攔截器實(shí)現(xiàn)用戶匿名和非匿名訪問,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 一篇文章帶你入門Java變量

    一篇文章帶你入門Java變量

    這篇文章主要介紹了Java變量,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • Java5種遍歷HashMap數(shù)據(jù)的寫法

    Java5種遍歷HashMap數(shù)據(jù)的寫法

    這篇文章主要介紹了Java5種遍歷HashMap數(shù)據(jù)的寫法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • 使用spring通過aop獲取方法參數(shù)和參數(shù)值

    使用spring通過aop獲取方法參數(shù)和參數(shù)值

    這篇文章主要介紹了使用spring通過aop獲取方法參數(shù)和參數(shù)值,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java SpringMVC自學(xué)自講

    Java SpringMVC自學(xué)自講

    本篇文章主要介紹了java SpringMVC——如何獲取請求參數(shù)詳解,詳細(xì)的介紹了每種參數(shù)注解的用法及其實(shí)例。感興趣的小伙伴們可以參考一下
    2021-09-09
  • 深入談?wù)刯ava的枚舉(enum)類型

    深入談?wù)刯ava的枚舉(enum)類型

    這篇文章介紹的是java中的枚舉類型,對于枚舉類型的相關(guān)知識,我們也介紹過不少方面的內(nèi)容。希望本文能夠給你帶來幫助,下面來一起看看,有需要的可以參考借鑒。
    2016-09-09
  • 代理角色java設(shè)計(jì)模式之靜態(tài)代理詳細(xì)介紹

    代理角色java設(shè)計(jì)模式之靜態(tài)代理詳細(xì)介紹

    查了好多資料,發(fā)現(xiàn)還是不全,干脆自己整理吧,至少保證在我的做法正確的,以免誤導(dǎo)讀者,也是給自己做個(gè)記錄吧!
    2013-05-05
  • RabbitMQ中的channel信道、exchange交換機(jī)和queue隊(duì)列詳解

    RabbitMQ中的channel信道、exchange交換機(jī)和queue隊(duì)列詳解

    這篇文章主要介紹了RabbitMQ中的channel信道、exchange交換機(jī)和queue隊(duì)列詳解,connection是指物理的連接,一個(gè)client與一個(gè)server之間有一個(gè)連接,一個(gè)連接上可以建立多個(gè)channel,可以理解為邏輯上的連接,需要的朋友可以參考下
    2023-08-08
  • JAVA提高第十篇 ArrayList深入分析

    JAVA提高第十篇 ArrayList深入分析

    這篇文章主要深入分析了JAVA提高第十篇ArrayList的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10

最新評論

留坝县| 鄂温| 焦作市| 常德市| 桃园市| 江阴市| 闽清县| 界首市| 怀柔区| 揭东县| 方正县| 张家川| 绿春县| 宜昌市| 武胜县| 通河县| 绥江县| 磐安县| 皋兰县| 康乐县| 阿拉善左旗| 邯郸县| 都兰县| 乌拉特后旗| 阜康市| 济源市| 长宁区| 竹溪县| 扶绥县| 大宁县| 灵宝市| 雅江县| 玛曲县| 沛县| 利辛县| 保山市| 河北省| 建平县| 灌阳县| 丰镇市| 平谷区|