單例設計模式:單例模式一共多少種?細分的話可達8種


說到單例模式,大家應該都有所了解,懶漢式、餓漢式馬上浮上心頭。

那么懶漢式和餓漢式有什么區別?除了常見的兩種,還有別的實現單例模式的方法嗎?


1、單例模式的概念(個人總結非官方):

  單例顧名思義就是程序運行中,最多只能有一個實例化的對象。(至於為什么這里不做介紹)

2、懶漢式、餓漢式的區別:

  區別實際上體現在加載時間上,餓漢式是在類加載的時候就加載;懶漢式是需要用到該實例時才加載。

   使用餓漢式的話,不管你用不用得到這個實例,它都會在類加載的時候加載;假如我一直沒使用到這個實例,是不是就浪費資源了?

   使用懶漢式的話,用到時候才會去加載,資源的利用上更為合理。

   總結:如果確定某個單例一定會用上,餓漢式是一種很合適方法;如果不一定會用的某個單例,懶漢式是比較合適的方法。

2、單例模式的實現

  2.1、餓漢式

    方法1:靜態變量方式(線程安全

  /*1.將構造方法私有化,外部無法使用new構造方法創建實例*/
    private Singleton1() {} /*2.內部創建對象*/
    private static Singleton1 instence = new Singleton1(); /*3.對外獲取實例的方法*/
    public static Singleton1 getInstence() { return instence; }

 

     方法2:靜態代碼塊方式(線程安全

  /*1.將構造方法私有化,外部無法使用new*/
    private Singleton2() {} /*2.內部靜態代碼塊中創建對象*/
    private static Singleton2 instence; static { instence = new Singleton2(); } /*3.對外獲取實例的方法*/
    public static Singleton2 getInstence() { return instence; }

  2.1、懶漢式

    方法3:簡單判斷非空(多線程並發不安全,單線程無影響

    /*1.將構造方法私有化,外部無法使用new*/
    private Singleton3() {} /*2.創建類成員變量instence*/
    private static Singleton3 instence; /*3.對外獲取實例的方法,先判斷instence是否為空,為空則創建*/
    public static Singleton3 getInstence() { if(instence == null) { instence = new Singleton3(); } return instence; }

 

    不安全的原因:

 

 

 

 

 

    方法4:synchronized鎖方法線程安全但是synchronized鎖了整個方法,下一個線程必須等上一個線程釋放鎖,效率很低,不建議使用

    /*1.將構造方法私有化,外部無法使用new*/
    private Singleton4() {} /*2.創建類成員變量instence*/
    private static Singleton4 instence; /*3.對外獲取實例的方法,先判斷instence是否為空,為空則創建*/
    public static synchronized Singleton4 getInstence() { if(instence == null) { instence = new Singleton4(); } return instence; }

 

    方法5:同步代碼塊多線程並發不安全

    /*1.將構造方法私有化,外部無法使用new*/
    private Singleton5() {} /*2.創建類成員變量instence*/
    private static Singleton5 instence; /*3.對外獲取實例的方法,先判斷instence是否為空,為空則創建*/
    public static Singleton5 getInstence() { if(instence == null) { synchronized (Singleton6.class) { instence = new Singleton5(); } } return instence; }

    不安全原因:與之前的描述一致,雖然它加了鎖,但是實際上沒有起到作用,如果很多線程已經同時進入if語句塊內,結果是一樣的。

    方法6:雙重檢查(線程安全這個方法比較常用   

    /*1.將構造方法私有化,外部無法使用new*/
    private Singleton6() {} /*2.創建類成員變量instence*/
    private static volatile Singleton6 instence; /*3.對外獲取實例的方法,雙重判斷*/
    public static Singleton6 getInstence() { if(instence == null) { synchronized (Singleton6.class) { if (instence == null){ instence = new Singleton6(); } } } return instence; }

 

    方法7:靜態內部類(線程安全這個方法比較常用

 

    /*1.將構造方法私有化,外部無法使用new*/
    private Singleton7() {} /*2.編寫一個靜態內部類*/
    private static class SingletonInstence { private static final Singleton7 INSTENCE = new Singleton7(); } /*3.提供一個靜態公有方法,直接返回SingletonInstence*/
    public static Singleton7 getInstence() { return SingletonInstence.INSTENCE; }

 

    方法8:枚舉線程安全,還可以防止反序列化重新生成的對象,推薦使用這個方法被大佬推薦使用,至於為啥博主暫時未去了解

     public class Singleton8{ } enum Sing{ insance; public void method(){} }

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM