1. 程式人生 > >設計模式-單例模式 Singleton

設計模式-單例模式 Singleton

1 好處

  • 1、 避免例項物件的重複建立,節約記憶體空間
  • 2、 能夠避免由於操作多個例項導致的邏輯錯誤

例子

  • 1、 正常的new物件
Singleton ns = new Singleton();
System.out.println("---new Singleton()>:"+ns);
Singleton ns2 = new Singleton();
System.out.println("---new Singleton()2>:"+ns2);
  • 列印結果 兩個不同的記憶體地址
---new Singleton()>:com
.qz.hesvit.planmode.Singleton@4a744a4d ---new Singleton()2>:com.qz.hesvit.planmode.Singleton@18ba2b6b
  • 2、 惡漢式
public class Singleton {
    // 一定要private修改構造方法,單例不能直接new物件
    private Singleton() {
    }
    //惡漢模式
    //在自己內部定義一個自己的例項,只供自己呼叫
    private static final Singleton singleton = new Singleton();
    public
static Singleton getInstance() { return singleton; } }
  • 測試和列印結果 相同的記憶體地址
Singleton s = Singleton.getInstance();
System.out.println("sss---"+s);
Singleton s2 = Singleton.getInstance();
System.out.println("sss2--"+s2);

//列印結果
sss---com.qz.hesvit.planmode.Singleton@4a744a4d
sss2--com
.qz.hesvit.planmode.Singleton@4a744a4d
  • 3、 懶漢式
public class Singleton {
    // 一定要private修改構造方法,單例不能直接new物件
    private Singleton() {
    }
    // 懶漢模式中單例是在需要的時候才去建立的
    private static Singleton singleton = null;
    public static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
    //但是這裡的懶漢模式並沒有考慮執行緒安全問題,在多個執行緒可能會併發呼叫它的
    //getInstance()方法,導致建立多個例項,因此需要加鎖解決執行緒同步問題,實現如下:
    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}
  • 測試和列印結果 相同的記憶體地址
Singleton s = Singleton.getInstance();
System.out.println("sss---"+s);
Singleton s2 = Singleton.getInstance();
System.out.println("sss2--"+s2);

//列印結果
sss---com.qz.hesvit.planmode.Singleton@4a744a4d
sss2--com.qz.hesvit.planmode.Singleton@4a744a4d
  • 4、 雙重加鎖
public class Singleton {
    // 一定要private修改構造方法,單例不能直接new物件
    private Singleton() {
    }
    //雙重加鎖
    /* 
    加鎖的懶漢模式看起來即解決了執行緒併發問題,又實現了延遲載入,然而它存在著效能問題,
    依然不夠完美。synchronized修飾的同步方法比一般方法要慢很多,
    如果多次呼叫getInstance(),累積的效能損耗就比較大了。
    因此就有了雙重校驗鎖,先看下它的實現程式碼。
    */
    private static Singleton singleton = null;
    public static Singleton getInstance() {
        if(null == singleton) {
            synchronized(Singleton.class) {
                if (singleton == null) {  //2重加鎖
                    singleton = new Singleton();
                }
                return singleton;
            }
        }
    }
}
  • 測試和列印結果 相同的記憶體地址
Singleton s = Singleton.getInstance();
System.out.println("sss---"+s);
Singleton s2 = Singleton.getInstance();
System.out.println("sss2--"+s2);

//列印結果
sss---com.qz.hesvit.planmode.Singleton@4a744a4d
sss2--com.qz.hesvit.planmode.Singleton@4a744a4d