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

java面試常見(jiàn)模式問(wèn)題---單例模式

 更新時(shí)間:2021年06月09日 11:49:53   作者:興趣使然の草帽路飛  
單例模式(Singleton Pattern)是 Java 中最簡(jiǎn)單的設(shè)計(jì)模式之一。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式

1、簡(jiǎn)介

單例模式使⽤場(chǎng)景

  • 業(yè)務(wù)系統(tǒng)全局只需要⼀個(gè)對(duì)象實(shí)例,⽐如發(fā)號(hào)器、 redis 連接對(duì)象等。
  • Spring IOC容器中的 Bean 默認(rèn)就是單例。
  • Spring Boot 中的 Controller、Service、Dao 層中通過(guò) @Autowire的依賴注⼊對(duì)象默認(rèn)都是單例的。

單例模式分類

  • 懶漢:就是所謂的懶加載,延遲創(chuàng)建對(duì)象,需要用的時(shí)候再創(chuàng)建對(duì)象。
  • 餓漢:與懶漢相反,提前創(chuàng)建對(duì)象。
  • 單例模式實(shí)現(xiàn)步驟:
  • 私有化構(gòu)造函數(shù)。
  • 提供獲取單例的方法。

2、單例模式——懶漢式

單例模式——懶漢式有以下⼏種實(shí)現(xiàn)⽅式:

/**
 * @Auther: csp1999
 * @Date: 2020/11/06/20:36
 * @Description: 單例設(shè)計(jì)模式-懶漢式
 */
public class SingletonLazy {
    // 當(dāng)需要用到該實(shí)例的時(shí)候再創(chuàng)建實(shí)例對(duì)象
    private static SingletonLazy instance;
    /**
     * 構(gòu)造函數(shù)私有化
     * 不能通過(guò) new SingletonLazy() 的方式創(chuàng)建實(shí)例
     * 
     * 當(dāng)需要用到該實(shí)例的時(shí)候在加載
     * 只能通過(guò) SingletonLazy.getInstance() 這種方式獲取實(shí)例
     */
    private SingletonLazy() {
    }
    /**
     * 單例對(duì)象的方法
     */
    public void process() {
        System.out.println("方法實(shí)例化成功!");
    }
    /**
     * 方式一:
     * <p>
     * 對(duì)外暴露一個(gè)方法獲取該類的對(duì)象
     * <p>
     * 缺點(diǎn):線程不安全,多線程下存在安全問(wèn)題
     *
     * @return
     */
    public static SingletonLazy getInstance() {
        if (instance == null) {// 實(shí)例為null時(shí)候才創(chuàng)建
            /**
             * 線程安全問(wèn)題:
             * 當(dāng)某一時(shí)刻,兩個(gè)或多個(gè)線程同時(shí)判斷到instance == null成立的時(shí)候
             * 這些線程同時(shí)進(jìn)入該if判斷內(nèi)部執(zhí)行實(shí)例化
             * 則會(huì)新建出不止一個(gè)SingletonLazy實(shí)例
             */
            instance = new SingletonLazy();// 當(dāng)需要的時(shí)候再進(jìn)行實(shí)例化對(duì)象
        }
        return instance;
    }
    /**
     * 方式二:
     * 通過(guò)加synchronized鎖 保證線程安全
     *
     * 采用synchronized 對(duì)方法加鎖有很大的性能開(kāi)銷
     * 因?yàn)楫?dāng)getInstance2()內(nèi)部邏輯比較復(fù)雜的時(shí)候,在高并發(fā)條件下
     * 沒(méi)獲取到加鎖方法執(zhí)行權(quán)的線程,都得等到這個(gè)方法內(nèi)的復(fù)雜邏輯執(zhí)行完后才能執(zhí)行,等待浪費(fèi)時(shí)間,效率比較低
     *
     * @return
     */
    public static synchronized SingletonLazy getInstance2() {
        if (instance == null) {// 實(shí)例為null時(shí)候才創(chuàng)建
            // 方法上加synchronized鎖后可以保證線程安全
            instance = new SingletonLazy();// 當(dāng)需要的時(shí)候再進(jìn)行實(shí)例化對(duì)象
        }
        return instance;
    }
    /**
     * 方式三:
     * 在getInstance3()方法內(nèi),針對(duì)局部需要加鎖的代碼塊加鎖,而不是給整個(gè)方法加鎖
     *
     * 也存在缺陷:
     * @return
     */
    public static SingletonLazy getInstance3() {
        if (instance == null) {// 實(shí)例為null時(shí)候才創(chuàng)建
            // 局部加鎖后可以保證線程安全,效率較高
            // 缺陷:假設(shè)線程A和線程B
            synchronized (SingletonLazy.class){
                // 當(dāng)線程A獲得鎖的執(zhí)行權(quán)的時(shí)候B等待 A執(zhí)行new SingletonLazy();實(shí)例化
                // 當(dāng)A線程執(zhí)行完畢后,B再獲得執(zhí)行權(quán),這時(shí)候還是可以實(shí)例化該對(duì)象
                instance = new SingletonLazy();// 當(dāng)需要的時(shí)候再進(jìn)行實(shí)例化對(duì)象
            }
        }
        return instance;
    }
}

單例模式:懶漢實(shí)現(xiàn) + 雙重檢查鎖定 + 內(nèi)存模型

對(duì)于上面方式三存在的缺陷,我們可以使用雙重檢查鎖定的方式對(duì)其進(jìn)行改進(jìn)

/**
 * 方式三改進(jìn)版本:
 * 在getInstance3()方法內(nèi),針對(duì)局部需要加鎖的代碼塊加鎖,而不是給整個(gè)方法加鎖
 *
 * DCL 雙重檢查鎖定 (Double-Checked-Locking) 在多線程情況下保持高性能
 *
 * 這是否安全? instance = new SingletonLazy(); 并不是原子性操作
 * jvm中 instance實(shí)例化內(nèi)存模型流程如下:
 * 1.分配空間給對(duì)象
 * 2.在空間內(nèi)創(chuàng)建對(duì)象
 * 3.將對(duì)象賦值給instance引用
 *
 * 假如出現(xiàn)如下順序錯(cuò)亂的情況:
 * 線程的執(zhí)行順序?yàn)椋? -> 3 -> 2, 那么這時(shí)候會(huì)把值寫回主內(nèi)存
 * 則,其他線程就會(huì)讀取到instance的最新值,但是這個(gè)是不完全的對(duì)象
 * (指令重排現(xiàn)象)
 *
 * @return
 */
public static SingletonLazy getInstance3plus() {
    if (instance == null) {// 實(shí)例為null時(shí)候才創(chuàng)建
        // 局部加鎖后可以保證線程安全,效率較高
        // 假設(shè)線程A和線程B 
        synchronized (SingletonLazy.class){// 第一重檢查
            // 當(dāng)線程A獲得鎖的執(zhí)行權(quán)的時(shí)候B等待 A執(zhí)行new SingletonLazy();實(shí)例化
            // 當(dāng)A線程執(zhí)行完畢后,B再獲得執(zhí)行權(quán),這時(shí)候再判斷instance == null是否成立
            // 如果不成立,B線程無(wú)法 實(shí)例化SingletonLazy
            if (instance == null){// 第二重檢查
                instance = new SingletonLazy();// 當(dāng)需要的時(shí)候再進(jìn)行實(shí)例化對(duì)象
            }
        }
    }
    return instance;
}

再次升級(jí)方式三,來(lái)解決內(nèi)存模型中的指令重排問(wèn)題

// 添加volatile 關(guān)鍵字,禁止實(shí)例化對(duì)象時(shí),內(nèi)存模型中出現(xiàn)指令重排現(xiàn)象
private static volatile SingletonLazy instance;
/**
 * 方式三再次升級(jí)版本:
 * 在getInstance3()方法內(nèi),針對(duì)局部需要加鎖的代碼塊加鎖,而不是給整個(gè)方法加鎖
 *
 * DCL 雙重檢查鎖定 (Double-Checked-Locking) 在多線程情況下保持高性能
 *
 * 解決指令重排問(wèn)題——禁止指令重排
 * @return
 */
public static SingletonLazy getInstance3plusplus() {
    if (instance == null) {// 實(shí)例為null時(shí)候才創(chuàng)建
        // 局部加鎖后可以保證線程安全,效率較高
        // 假設(shè)線程A和線程B
        synchronized (SingletonLazy.class){// 第一重檢查
            // 當(dāng)線程A獲得鎖的執(zhí)行權(quán)的時(shí)候B等待 A執(zhí)行new SingletonLazy();實(shí)例化
            // 當(dāng)A線程執(zhí)行完畢后,B再獲得執(zhí)行權(quán),這時(shí)候再判斷instance == null是否成立
            // 如果不成立,B線程無(wú)法 實(shí)例化SingletonLazy
            if (instance == null){// 第二重檢查
                instance = new SingletonLazy();// 當(dāng)需要的時(shí)候再進(jìn)行實(shí)例化對(duì)象
            }
        }
    }
    return instance;
}

單例模式——懶漢式調(diào)用:

@Test
public void testSingletonLazy(){
    SingletonLazy.getInstance().process();
}

3、單例模式——餓漢式

/**
 * @Auther: csp1999
 * @Date: 2020/11/06/21:39
 * @Description: 單例設(shè)計(jì)模式-餓漢式
 */
public class SingletonHungry {
    // 當(dāng)類加載的時(shí)候就直接實(shí)例化對(duì)象
    private static SingletonHungry instance = new SingletonHungry();
    private SingletonHungry(){}
    /**
     * 單例對(duì)象的方法
     */
    public void process() {
        System.out.println("方法實(shí)例化成功!");
    }
    public static SingletonHungry getInstance(){
        return instance;// 當(dāng)類加載的時(shí)候就直接實(shí)例化對(duì)象
    }
}

單例模式——餓漢式調(diào)用:

@Test
public void testSingletonHungry(){
    SingletonHungry.getInstance().process();
}

餓漢式單例模式,當(dāng)類加載的時(shí)候就直接實(shí)例化對(duì)象,因此不需要考慮線程安全問(wèn)題。

  • 優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,不需要考慮線程安全問(wèn)題。
  • 缺點(diǎn):不管有沒(méi)有使用該對(duì)象實(shí)例,instance對(duì)象一直占用著這段內(nèi)存。

懶漢與餓漢式如何選擇?

  • 如果對(duì)象內(nèi)存占用不大,且創(chuàng)建不復(fù)雜,直接使用餓漢的方式即可。
  • 其他情況均采用懶漢方式(優(yōu)選)。

總結(jié)

文章會(huì)不定時(shí)更新,有時(shí)候一天多更新幾篇,如果幫助您復(fù)習(xí)鞏固了知識(shí)點(diǎn),還請(qǐng)支持一下,后續(xù)會(huì)億點(diǎn)點(diǎn)的更新!希望大家多多關(guān)注腳本之家的其他內(nèi)容!

相關(guān)文章

  • Java實(shí)現(xiàn)部門員工管理

    Java實(shí)現(xiàn)部門員工管理

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)部門員工管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • MyBatis實(shí)現(xiàn)樂(lè)觀鎖和悲觀鎖的示例代碼

    MyBatis實(shí)現(xiàn)樂(lè)觀鎖和悲觀鎖的示例代碼

    在數(shù)據(jù)庫(kù)操作中,樂(lè)觀鎖和悲觀鎖是兩種常見(jiàn)的并發(fā)控制策略,本文主要介紹了MyBatis實(shí)現(xiàn)樂(lè)觀鎖和悲觀鎖的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • 快速了解JAVA中的Random()函數(shù)

    快速了解JAVA中的Random()函數(shù)

    這篇文章主要介紹了JAVA中的Random()函數(shù)的使用方法,文中代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • 談?wù)剬?duì)Java多態(tài)性的一點(diǎn)理解

    談?wù)剬?duì)Java多態(tài)性的一點(diǎn)理解

    多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過(guò)該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量倒底會(huì)指向哪個(gè)類的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定
    2017-08-08
  • SpringBoot的HTTPS配置實(shí)現(xiàn)

    SpringBoot的HTTPS配置實(shí)現(xiàn)

    本文主要介紹了SpringBoot的HTTPS配置實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Java 注解@PostConstruct的原理及使用場(chǎng)景

    Java 注解@PostConstruct的原理及使用場(chǎng)景

    @PostConstruct 是 Java 中用于標(biāo)記初始化方法的注解,本文將詳細(xì)講解 @PostConstruct 的原理、使用場(chǎng)景及最佳實(shí)踐,感興趣的朋友一起看看吧
    2025-04-04
  • Java8接口的默認(rèn)方法

    Java8接口的默認(rèn)方法

    這篇文章主要為大家介紹了Java8接口的默認(rèn)方法,還為大家默認(rèn)方法的多重繼承,感興趣的朋友可以參考一下
    2016-01-01
  • springboot 2.x整合mybatis實(shí)現(xiàn)增刪查和批量處理方式

    springboot 2.x整合mybatis實(shí)現(xiàn)增刪查和批量處理方式

    這篇文章主要介紹了springboot 2.x整合mybatis實(shí)現(xiàn)增刪查和批量處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java服務(wù)中的大文件上傳和下載優(yōu)化技巧分享

    Java服務(wù)中的大文件上傳和下載優(yōu)化技巧分享

    在Java服務(wù)中處理大文件的上傳和下載是一項(xiàng)常見(jiàn)但復(fù)雜的任務(wù),為了提供優(yōu)秀的用戶體驗(yàn)和高效的系統(tǒng)性能,我們將探索多種策略和技術(shù),并在每一點(diǎn)上都提供代碼示例以便實(shí)戰(zhàn)應(yīng)用,需要的朋友可以參考下
    2023-10-10
  • Springboot項(xiàng)目編寫測(cè)試單元完整步驟記錄

    Springboot項(xiàng)目編寫測(cè)試單元完整步驟記錄

    這篇文章主要介紹了如何使用JUnit編寫Spring?Boot項(xiàng)目中的測(cè)試單元,包括引入依賴、配置文件設(shè)置、啟動(dòng)文件創(chuàng)建以及編寫測(cè)試類的步驟,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03

最新評(píng)論

巫溪县| 峨边| 九寨沟县| 新竹市| 乌兰浩特市| 大城县| 乌兰察布市| 双峰县| 五指山市| 准格尔旗| 永寿县| 康保县| 眉山市| 玉龙| 比如县| 平舆县| 徐水县| 全南县| 麦盖提县| 依安县| 苏尼特左旗| 阿拉善右旗| 涡阳县| 东台市| 萝北县| 昌图县| 铜川市| 芦溪县| 大足县| 蓝田县| 昭通市| 太保市| 同心县| 阿勒泰市| 福建省| 达孜县| 内乡县| 高安市| 锦屏县| 壤塘县| 团风县|