亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺析Java單例設(shè)計模式(自寫demo)

 更新時間:2021年12月14日 16:01:07   作者:海深不見鯨  
Java單例模式是看起來以及用起來簡單的一種設(shè)計模式,但是就實現(xiàn)方式以及原理來說,也并不淺顯,下面這篇文章主要給大家詳細介紹了Java中單例模式,需要的朋友可以參考下

單例模式特點

1、構(gòu)造器私有

2、在一個Java應(yīng)用程序中,可保證只有一個實例對象

3、只提供一個供外界調(diào)用的getInstance()方法

單例模式優(yōu)點

1、減少某些對象的頻繁創(chuàng)建,降低系統(tǒng)開銷和內(nèi)存占用

2、外部調(diào)用不使用new關(guān)鍵字,降低系統(tǒng)內(nèi)存的使用頻率

3、對于特殊的類,在系統(tǒng)中只能存在一個實例,否則系統(tǒng)無法正常運行,比如Controller

實現(xiàn)方式

這里簡單介紹兩種實現(xiàn)方式

餓漢式(線程安全)

/**
 * @author: xuzhilei6656
 * @create: 2021-12-12 12:07
 * @description: 單例模式(餓漢式)
 **/
public class Singleton {
    //創(chuàng)建實例
    private static Singleton instance = new Singleton();
 
    //私有構(gòu)造器
    private Singleton(){
    }
 
    //獲取實例的靜態(tài)方法
    public static Singleton getInstance(){
        return instance;
    }
 
}

實例對象在類被加載的時候就已經(jīng)完成初始化,外界調(diào)用拿到的都是這個唯一的實例對象

懶漢式

/**
 * @author: xuzhilei6656
 * @create: 2021-12-12 12:22
 * @description: 單例模式(懶漢式)
 **/
public class Singleton {
    //聲明一個變量
    private static Singleton instance;
 
    //私有構(gòu)造器
    private Singleton(){
    }
 
    //獲取實例的靜態(tài)方法
    public static Singleton getInstance(){
        //如果是首次調(diào)用,實例對象還沒有被創(chuàng)建,就需要創(chuàng)建,否則都是返回已經(jīng)創(chuàng)建過的那個對象
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
 
}

對比餓漢式可見,實例對象在類被加載的時候并沒有進行創(chuàng)建,在首次調(diào)用的時候才被創(chuàng)建,以后再被調(diào)用,返回的也是那個唯一的實例對象。

在多線程情況下,這種寫法存在線程安全問題,比如:線程A在執(zhí)行完if判斷條件后進入阻塞狀態(tài),此時并沒有進行對象創(chuàng)建,此時線程B來了,在執(zhí)行完if條件后直接進行對象創(chuàng)建,等線程A恢復(fù)運行狀態(tài)后也會進行對象創(chuàng)建,這個時候就不符合單例模式了,即出現(xiàn)了線程不安全的問題。

解決方案:在獲取實例的靜態(tài)方法上加synchronized關(guān)鍵字,即加鎖

/**
 * @author: xuzhilei6656
 * @create: 2021-12-12 12:22
 * @description: 單例模式(懶漢式)
 **/
public class Singleton {
    //聲明一個變量
    private static Singleton instance;
 
    //私有構(gòu)造器
    private Singleton(){
    }
 
    //獲取實例的靜態(tài)方法
    public static synchronized Singleton getInstance(){
        //如果是首次調(diào)用,實例對象還沒有被創(chuàng)建,就需要創(chuàng)建,否則都是返回已經(jīng)創(chuàng)建過的那個對象
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
 
}

簡單粗暴,可達到我們的目的,但是每次獲取實例對象都要有加鎖操作,影響系統(tǒng)性能。

改進后的方案:雙重檢查

/**
 * @author: xuzhilei6656
 * @create: 2021-12-12 12:22
 * @description: 單例模式(懶漢式)
 **/
public class Singleton {
    //聲明一個變量
    private static Singleton instance;
 
    //私有構(gòu)造器
    private Singleton(){
    }
 
    //獲取實例的靜態(tài)方法
    public static synchronized Singleton getInstance(){
        //第一次檢查
        if (instance == null){
            //獲取鎖
            synchronized (Singleton.class){
                //第二次檢查
                if (instance==null){
                    //兩次檢查都確定沒有已存在的實例對象,這才進行對象的創(chuàng)建操作
                    instance = new Singleton();
                }
            }
            
        }
        return instance;
    }
 
}

這樣不必每次獲取實例對象的時候都進行加鎖操作,只有在第一次創(chuàng)建對象的時候才進行加鎖操作,提高了系統(tǒng)性能。

但是,即使這樣有可能會出現(xiàn)。因為 instance = new Singleton()這行代碼在JVM中是兩個操作,賦值和初始化實例,但JVM并不保證這兩個操作的順序,有可能JVM給新對象分配了空間,直接賦值給instance變量,然后才去做初始化實例操作。比如下面這種情況

1,A,B兩個線程都進入第一個if條件

2,A線程先搶到鎖進入到synchronized代碼塊,執(zhí)行了instance = new Singleton()這行代碼,然后釋放鎖,此時有可能JVM只給實例對象分配了空白的內(nèi)存空間,并沒有執(zhí)行初始化操作

3,B線程搶到鎖,進入到synchronized代碼塊,第二次判斷的時候發(fā)現(xiàn)instance不是null,直接返回使用卻發(fā)現(xiàn)得到的對象還沒有被初始化,于是出現(xiàn)了問題。

再次改進:使用volatile關(guān)鍵字修飾聲明的成員變量instance

/**
 * @author: xuzhilei6656
 * @create: 2021-12-12 12:22
 * @description: 單例模式(懶漢式)
 **/
public class Singleton {
    //聲明變量,被volatile修飾
    private volatile static Singleton instance;
 
    //私有構(gòu)造器
    private Singleton(){
    }
 
    //獲取實例的靜態(tài)方法
    public static synchronized Singleton getInstance(){
        //第一次檢查
        if (instance == null){
            //獲取鎖
            synchronized (Singleton.class){
                //第二次檢查
                if (instance==null){
                    //兩次檢查都確定沒有已存在的實例對象,這才進行對象的創(chuàng)建操作
                    instance = new Singleton();
                }
            }
 
        }
        return instance;
    }
 
}

volatile關(guān)鍵字作用:通過volatile修飾的變量,不會被線程本地緩存,所有線程對該對象的讀寫都會第一時間同步到主內(nèi)存,從而保證多個線程間該對象的準確性。

這個寫法已經(jīng)比較完美了,既能保證安全的創(chuàng)建出唯一實例,又不會對系統(tǒng)性能有太大影響。

不過,還有更優(yōu)的寫法:靜態(tài)內(nèi)部類實現(xiàn)

?
/**
 * @author: xuzhilei6656
 * @create: 2021-12-12 15:17
 * @description: 單例模式
 **/
public class Singleton {
 
    //私有構(gòu)造器
    private Singleton() {
    }
 
    //靜態(tài)內(nèi)部類聲明實例
    private static class SingletonFactory{
        private static Singleton instance = new Singleton();
    }
 
    //獲取實例的靜態(tài)方法
    public static Singleton getInstance(){
        return SingletonFactory.instance;
    }
    
}
 
?

使用內(nèi)部類來維護單例的實現(xiàn),JVM內(nèi)部的機制能夠保證當(dāng)一個類被加載的時候,這個類的加載過程是線程互斥的。這樣當(dāng)我們第一次調(diào)用getInstance()方法的時候,JVM能夠保證創(chuàng)建出唯一的實例對象,并且這個實例對象是已經(jīng)被初始化完成的,就解決了上面的線程安全問題

最后一種實現(xiàn)單例的寫法也很完美,代碼最簡潔

通過枚舉

/**
 * @author: xuzhilei6656
 * @create: 2021-12-12 15:33
 * @description: 單例模式
 **/
public enum Singleton {
 
    //代表一個Singleton實例
    INSTANCE;
}

通過枚舉來實現(xiàn)單實例代碼更加簡潔,而且JVM從根本上保證實例對象的唯一性,是更簡潔、高效、安全的實現(xiàn)單例的方式?

以上就是淺析Java單例設(shè)計模式(自寫demo)的詳細內(nèi)容,更多關(guān)于Java單例模式的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Redis介紹和使用場景詳解

    Redis介紹和使用場景詳解

    這篇文章主要為大家詳細介紹了Redis介紹和使用場景,需要的朋友可以參考,具體內(nèi)容如下
    2018-04-04
  • SpringBoot 整合 Shiro 密碼登錄與郵件驗證碼登錄功能(多 Realm 認證)

    SpringBoot 整合 Shiro 密碼登錄與郵件驗證碼登錄功能(多 Realm 認證)

    這篇文章主要介紹了SpringBoot 整合 Shiro 密碼登錄與郵件驗證碼登錄(多 Realm 認證),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • SpringCloud feign無法注入接口的問題

    SpringCloud feign無法注入接口的問題

    這篇文章主要介紹了SpringCloud feign無法注入接口的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • 使用Java實現(xiàn)驗證碼程序

    使用Java實現(xiàn)驗證碼程序

    這篇文章主要為大家詳細介紹了使用Java實現(xiàn)驗證碼程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Spring Cloud 請求重試機制核心代碼分析

    Spring Cloud 請求重試機制核心代碼分析

    這篇文章主要介紹了Spring Cloud 請求重試機制核心代碼分析,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • SpringBoot使用Jsp的示例代碼

    SpringBoot使用Jsp的示例代碼

    這篇文章主要介紹了SpringBoot使用Jsp的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • JAVA代碼塊你了解嗎

    JAVA代碼塊你了解嗎

    這篇文章主要介紹了舉例說明Java中的代碼塊,包括靜態(tài)屬性和非靜態(tài)屬性以及構(gòu)造函數(shù)等相關(guān)的執(zhí)行先后,需要的朋友可以參考下
    2021-09-09
  • mybatis-plus的SafetyEncryptProcessor安全加密處理示例解析

    mybatis-plus的SafetyEncryptProcessor安全加密處理示例解析

    這篇文章主要為大家介紹了mybatis-plus的SafetyEncryptProcessor安全加密處理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • java如何連續(xù)執(zhí)行多條cmd命令

    java如何連續(xù)執(zhí)行多條cmd命令

    這篇文章主要介紹了java如何連續(xù)執(zhí)行多條cmd命令的方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • MyBatis_Generator插件的安裝以及簡單使用方法(圖解)

    MyBatis_Generator插件的安裝以及簡單使用方法(圖解)

    下面小編就為大家?guī)硪黄狹yBatis_Generator插件的安裝以及簡單使用方法(圖解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05

最新評論