国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Java EE初階六】多線程案例(單例模式)

這篇具有很好參考價值的文章主要介紹了【Java EE初階六】多線程案例(單例模式)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1. 單例模式

????????單例模式是一種設(shè)計模式,設(shè)計模式是我們必須要掌握的一個技能;

1.1 關(guān)于框架和設(shè)計模式

????????設(shè)計模式是軟性的規(guī)定,且框架是硬性的規(guī)定,這些都是技術(shù)大佬已經(jīng)設(shè)計好的;

????????一般來說設(shè)計模式有很多種,且不同的語言會有不同的設(shè)計模式,(同時設(shè)計模式也可以理解為對編程語言的一種補(bǔ)充

1.2 細(xì)說單例模式

????????單例 = 單個實例(對象);

????????某個類,在一個線程中,只應(yīng)該創(chuàng)建一個實例化對象(原則上不應(yīng)該有多個),這時就使用單例模式,如此可以對我們的代碼進(jìn)行一個更嚴(yán)格的校驗和檢查。

????????保證對象唯一性的方法:

????????方法一,可以通過“協(xié)議約束”,寫一個文檔,規(guī)定這個類只能有唯一的實例,程序員在接手這個代碼時,就會發(fā)現(xiàn)這個文檔已經(jīng)進(jìn)行約定,其中的規(guī)定約束著程序員在創(chuàng)建對象時,時刻注意只能創(chuàng)建一個對象。

????????方法二:從機(jī)器入手;讓機(jī)器幫我們檢查,我們期望讓機(jī)器幫我們對代碼中指定的類,創(chuàng)建類的實例個數(shù)進(jìn)行檢查、校驗,當(dāng)創(chuàng)建的實例個數(shù)超過我們期望個數(shù),就編譯報錯。其中單例模式就是已經(jīng)設(shè)計好的套路,可以實現(xiàn)這種預(yù)期效果。

? ? ? ? 關(guān)于單例模式代碼實現(xiàn)的基本方式有兩種:餓漢模式和懶漢模式;

2. 餓漢模式

????????餓漢模式是指創(chuàng)建實例的時期非常早;在類加載的時候,程序一啟動,就已經(jīng)創(chuàng)建好實例了,使用 “餓漢”這個詞,就是形容創(chuàng)建實例非常迫切,非常早。單例模式代碼如下:

class Singleton {
    private static Singleton instance = new Singleton();
    public static Singleton getInstance() {
        return instance;
    }
    private Singleton(){ }
}
public class TestDemo4 {
    public static void main(String[] args) {
        Singleton singleton = new Singleton();
    }
}

? ? ? ? 當(dāng)我們運(yùn)行該代碼時,系統(tǒng)就會報錯,接下來我們詳細(xì)的分析一下此處的代碼;?

【Java EE初階六】多線程案例(單例模式),JAVA EE 初階,單例模式,java-ee,java

????????這樣,如果我們想new一個Singleton對象,也new不了,同時不管我們用getInstance獲取多少次實例,獲取的對象都是同一個對象,代碼如下:

package thread;

// 就期望這個類只能有唯一的實例 (一個進(jìn)程中)
class Singleton {
    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }

    private Singleton() {}
}

public class ThreadDemo26 {
    public static void main(String[] args) {
        // Singleton s = new Singleton();
        Singleton s = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        System.out.println(s == s2);
    }
}

? ? ? ? 結(jié)果如下:

【Java EE初階六】多線程案例(單例模式),JAVA EE 初階,單例模式,java-ee,java

3. 懶漢模式

????????和餓漢模式不一樣的是,懶漢模式創(chuàng)建實例的時機(jī)比較晚,沒餓漢創(chuàng)建實例那么迫切,只有第一次使用這個類時,才會創(chuàng)建實例,代碼如下:

class SingletonLazy {
    private static SingletonLazy instance = null;
    public static SingletonLazy getInstance() {
        if(instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
    private SingletonLazy() { }
}
public class TestDemo5 {
    public static void main(String[] args) {
 
    }
}

? ? ? ? 下面為代碼圖解分析:

【Java EE初階六】多線程案例(單例模式),JAVA EE 初階,單例模式,java-ee,java

????????和餓漢模式的區(qū)別就是沒那么迫切創(chuàng)建實例,等需要調(diào)用這個類的時候才創(chuàng)建一個實例,而餓漢模式是有了這個類就創(chuàng)建出實例。

????????懶漢模式的優(yōu)點:有的程序,要在一定條件下,才需要進(jìn)行相關(guān)的操作,有時候不滿足這個條件,也就不需要完成這個操作了,如此哦·就把這個操作省下來了。

4. 兩種模式關(guān)于線程安全

4.1 餓漢模式

? ? ? ? 線程安全;

【Java EE初階六】多線程案例(單例模式),JAVA EE 初階,單例模式,java-ee,java

? ? ? ? 對于餓漢模式來說,上圖所示通過調(diào)用getinstance方法來返回instance對象,本質(zhì)上來說是讀操作;

????????當(dāng)有多個線程,同時并發(fā)執(zhí)行,調(diào)用getInstance方法,取instance,這時線程是安全的,因為只涉及到讀,多線程讀取同一個變量,是線程安全的。而instance很早之前就已經(jīng)創(chuàng)建好了,不會修改它,一直也只有這一個實例,也不涉及寫的操作。

4.2?懶漢模式

? ? ? ? 線程不安全;

????????在懶漢模式中,條件判定和返回時是讀操作,new一個對象是寫操作;

? ? ? ?我們只有調(diào)用getInstance方法后,就會創(chuàng)建出實例來,如果多個線程同時調(diào)用這個方法,此時SingletonLazy類里面的instance都為null,那么這些線程都會new對象,就會創(chuàng)建多個實例。這時,就不符合我們單例模式的預(yù)期了,所以,這個代碼是線程不安全的。

????????線程不安全的直接原因,就是 “寫” 操作不是原子的。

4.3?解決懶漢模式的線程安全問題

4.3.1 把寫操作打包成原子

????????因為多線程并發(fā)執(zhí)行的時候,可能讀到的都是instance == null,所以會創(chuàng)建多個實例,那我們就給它加鎖,讓它在創(chuàng)建實例的時候,只能創(chuàng)建一個,加鎖代碼如下:

class SingletonLazy {
    private static Object locker = new Object();
    private static SingletonLazy instance = null;
    public static SingletonLazy getInstance() {
        synchronized (locker) {
            if(instance == null) {
                instance = new SingletonLazy();
            }
        }
        return instance;
    }
    private SingletonLazy() { }
}

? ? ? ? 以上操作雖然將寫操作打包成了一個原子,但是新的問題也出現(xiàn)了;

4.3.2?去除冗余操作

?????????上述操作加上了還是有問題:如果已經(jīng)創(chuàng)建出實例了,我們還有加鎖來判斷它是不是null嗎,加鎖這些操作也是要消耗硬件資源的,沒有必要為此浪費資源空間,如果已經(jīng)不是null了,我們就想讓它直接返回,不再進(jìn)行加鎖操作,代碼修改如下:

class SingletonLazy {
    private static Object locker = new Object();
    private static SingletonLazy instance = null;
    public static SingletonLazy getInstance() {
        if (instance == null) {
            synchronized (locker) {
                if (instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
    private SingletonLazy() { }
}

? ? ? ? 代碼圖解分析兩個判斷語句的是目的意義:

【Java EE初階六】多線程案例(單例模式),JAVA EE 初階,單例模式,java-ee,java

4.3.3 指令重排序的問題

????????指令重排序:指令重排序也是編譯器的一種優(yōu)化,在保證原代碼的邏輯不變,調(diào)整原代碼的指令執(zhí)行順序,從而讓程序的執(zhí)行效率提高。

????????保證原代碼的邏輯不變,改變原有指令的順序,從而提高代碼的執(zhí)行效率,其中這個代碼,就存在著指令重排序的優(yōu)化,如下圖代碼:

【Java EE初階六】多線程案例(單例模式),JAVA EE 初階,單例模式,java-ee,java

該語句原本指令執(zhí)行順序:

????????1、去內(nèi)存申請一段空間

????????2、在這個內(nèi)存中調(diào)用構(gòu)造方法,創(chuàng)建實例

????????3、從內(nèi)存中取出地址,賦值給這個實例instance。

指令重排序后的順序:1, 3 , 2;按照指令重排序后的代碼執(zhí)行邏輯就變成了下面所示:

????????假設(shè)有兩個線程,現(xiàn)在執(zhí)行順序如下圖所示:

【Java EE初階六】多線程案例(單例模式),JAVA EE 初階,單例模式,java-ee,java

????????因為指令重排序后,先去內(nèi)存申請一段空間,然后是賦值給instance,那這時,instance就不是null了,第二個線程不會進(jìn)入到if語句了,直接返回instance,可是instance還沒有創(chuàng)建出實例,這樣返回肯定是有問題的,如此也就線程不安全了。

????????解決方案:

????????給instance這個變量,加volatile修飾,強(qiáng)制取消編譯器的優(yōu)化,不能指令重排序,同時也排除了內(nèi)存可見性的問題。

????????加volatile后的代碼如下:


?

class SingletonLazy {
    private static Object locker = new Object();
    private static volatile SingletonLazy instance = null;
    public static SingletonLazy getInstance() {
        if (instance == null) {
            synchronized (locker) {
                if (instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
    private SingletonLazy() { }
}

? ? ? ? 至此,我們才算解決掉懶漢模式關(guān)于線程安全的所有問題;

4.4 懶漢模式線程安全的代碼

package thread;

// 懶漢的方式實現(xiàn)單例模式.
class SingletonLazy {
    // 這個引用指向唯一實例. 這個引用先初始化為 null, 而不是立即創(chuàng)建實例
    private volatile static SingletonLazy instance = null;
    private static Object locker = new Object();
    public static SingletonLazy getInstance() {
        // 如果 Instance 為 null, 就說明是首次調(diào)用, 首次調(diào)用就需要考慮線程安全問題, 就要加鎖.
        // 如果非 null, 就說明是后續(xù)的調(diào)用, 就不必加鎖了.
        if (instance == null) {
            synchronized (locker) {
                if (instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
    private SingletonLazy() { }
}

public class ThreadDemo27 {
    public static void main(String[] args) {
        SingletonLazy s1 = SingletonLazy.getInstance();
        SingletonLazy s2 = SingletonLazy.getInstance();
        System.out.println(s1 == s2);
    }
}

? ? ? ? 結(jié)果如下:

【Java EE初階六】多線程案例(單例模式),JAVA EE 初階,單例模式,java-ee,java

ps:本次的內(nèi)容就到這里了,如果感興趣的話,就請一鍵三連哦?。?!文章來源地址http://www.zghlxwxcb.cn/news/detail-774048.html

到了這里,關(guān)于【Java EE初階六】多線程案例(單例模式)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【Java多線程】關(guān)于多線程的一些案例 —— 單例模式中的餓漢模式和懶漢模式以及阻塞隊列

    【Java多線程】關(guān)于多線程的一些案例 —— 單例模式中的餓漢模式和懶漢模式以及阻塞隊列

    目錄 1、單例模式 1.1、餓漢模式 2.1、懶漢模式? 2、阻塞隊列 2.1、BlockingQueue 阻塞隊列數(shù)據(jù)結(jié)構(gòu) 對框架和設(shè)計模式的簡單理解就是,這兩者都是“大佬”設(shè)計出來的,讓即使是一個代碼寫的不太好的“菜雞程序員”也能寫出還可以的代碼。 設(shè)計模式也可以認(rèn)為是對編程語言語

    2024年03月23日
    瀏覽(27)
  • 【Java EE初階三 】線程的狀態(tài)與安全(下)

    【Java EE初階三 】線程的狀態(tài)與安全(下)

    ??????? ?線程安全 : 某個代碼,不管它是單個線程執(zhí)行,還是多個線程執(zhí)行,都不會產(chǎn)生bug,這個情況就成為“線程安全”。 ???????? 線程不安全 : 某個代碼,它單個線程執(zhí)行,不會產(chǎn)生bug,但是多個線程執(zhí)行,就會產(chǎn)生bug,這個情況就成為 “線程不安全”,或者

    2024年02月03日
    瀏覽(20)
  • 【JAVA】Java 中什么叫單例設(shè)計模式?請用 Java 寫出線程安全的單例模式

    【JAVA】Java 中什么叫單例設(shè)計模式?請用 Java 寫出線程安全的單例模式

    ?? 個人博客: 個人主頁 ?? 個人專欄: JAVA ???? 功不唐捐,玉汝于成 目錄 前言 正文 懶漢式(Lazy Initialization): 雙重檢查鎖定(Double-Checked Locking): 結(jié)語 我的其他博客 在軟件設(shè)計中,單例設(shè)計模式是一種重要的設(shè)計思想,它確保了一個類只有一個實例,并提供了一

    2024年01月15日
    瀏覽(23)
  • Java多線程基礎(chǔ)-8:單例模式及其線程安全問題

    Java多線程基礎(chǔ)-8:單例模式及其線程安全問題

    單例模式是經(jīng)典的設(shè)計模式之一。什么是設(shè)計模式?代碼的設(shè)計模式類似于棋譜,棋譜就是一些下棋的固定套路,是前人總結(jié)出來的一些固定的打法。依照棋譜來下棋,不說能下得非常好,但至少是有跡可循,不會下得很糟糕。代碼的設(shè)計模式也是一樣。 設(shè)計模式,就是軟件

    2024年02月05日
    瀏覽(18)
  • Java 枚舉實現(xiàn)單例模式,線程安全又優(yōu)雅!

    Java 枚舉實現(xiàn)單例模式,線程安全又優(yōu)雅!

    這種DCL寫法的優(yōu)點:不僅線程安全,而且延遲加載。 1.1 為什么要double check?去掉第二次check行不行? 當(dāng)然不行,當(dāng)2個線程同時執(zhí)行g(shù)etInstance方法時,都會執(zhí)行第一個if判斷,由于鎖機(jī)制的存在,會有一個線程先進(jìn)入同步語句,而另一個線程等待,當(dāng)?shù)谝粋€線程執(zhí)行了 new Sin

    2024年02月02日
    瀏覽(20)
  • Java 多線程系列Ⅳ(單例模式+阻塞式隊列+定時器+線程池)

    Java 多線程系列Ⅳ(單例模式+阻塞式隊列+定時器+線程池)

    設(shè)計模式就是軟件開發(fā)中的“棋譜”,軟件開發(fā)中也有很多常見的 “問題場景”。針對這些問題場景,大佬們總結(jié)出了一些固定的套路。按照這些套路來實現(xiàn)代碼可能不會很好,但至少不會很差。當(dāng)前階段我們需要掌握兩種設(shè)計模式: (1)單例模式 (2)工廠模式 概念/特征

    2024年02月09日
    瀏覽(25)
  • 【Java中23種設(shè)計模式-單例模式2--懶漢式2線程安全】

    【Java中23種設(shè)計模式-單例模式2--懶漢式2線程安全】

    加油,新時代打工人! 簡單粗暴,學(xué)習(xí)Java設(shè)計模式。 23種設(shè)計模式定義介紹 Java中23種設(shè)計模式-單例模式 Java中23種設(shè)計模式-單例模式2–懶漢式線程不安全 通過運(yùn)行結(jié)果看,兩個線程的地址值是相同的,說明內(nèi)存空間里,創(chuàng)建了一個對象。

    2024年02月20日
    瀏覽(29)
  • Java設(shè)計模式之創(chuàng)建型-單例模式(UML類圖+案例分析)

    Java設(shè)計模式之創(chuàng)建型-單例模式(UML類圖+案例分析)

    目錄 一、基礎(chǔ)概念 二、UML類圖 三、角色設(shè)計 四、案例分析 4.1、餓漢模式 4.2、懶漢模式(線程不安全) 4.3、懶漢模式(線程安全) 4.4、雙重檢索模式 4.5、靜態(tài)內(nèi)部類 4.6、枚舉? 五、總結(jié) 單例模式確保一個類只有一個實例,提供一個全局訪問點。一般實現(xiàn)方式是把構(gòu)造函

    2024年02月13日
    瀏覽(46)
  • 【JavaEE初階】多線程(三)volatile wait notify關(guān)鍵字 單例模式

    【JavaEE初階】多線程(三)volatile wait notify關(guān)鍵字 單例模式

    攝影分享~~ 以上代碼運(yùn)行的結(jié)果可能是輸入1后,t1這個線程并沒有結(jié)束。而是一直在while中循環(huán)。而t2線程已經(jīng)執(zhí)行完了。 以上情況,就叫做 內(nèi)存可見性問題 這里使用匯編來理解,大概分為兩步操作: load,把內(nèi)存中flag的值,讀到寄存器中。 cmp,把寄存器中的值,和0進(jìn)行比

    2023年04月25日
    瀏覽(20)
  • 多線程案例-單例模式

    多線程案例-單例模式

    設(shè)計模式好比象棋中的\\\"棋譜\\\".紅方當(dāng)頭炮,黑方馬來跳.針對紅方的一些走法,黑方應(yīng)招的時候有一些固定的套路.按照套路來走局勢就不會吃虧. 軟件開發(fā)中也有很多常見的\\\"問題場景\\\".針對這些問題的場景,大佬們總結(jié)出了一些固定的套路.按照這些套路來實現(xiàn)代碼,也不會吃虧 單例

    2024年02月04日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包