設(shè)計模式學(xué)習(xí)05----之單例模式
單例模式,是我們最常用也最熟悉的一種設(shè)計模式,其使用要注意線程安全。
定義
單例模式:顧名思義,就是在應(yīng)用中有且只有一個實例。一般類似于計數(shù)器類的都必須是單例,多例會導(dǎo)致計數(shù)結(jié)果不準(zhǔn)。
一般而言,其分為餓漢式和懶漢式。
懶漢式
懶漢式:顧名思義,就是不在系統(tǒng)加載時創(chuàng)建類的實例。而是在調(diào)用時才去一次性創(chuàng)建。
demo如下:
package com.singleton;
/**
* 懶漢式
* @author xiang.wei
*/
public class LazySingleton {
/**
* 定義一個私有變量,目的是外部不能直接訪問該變量,必須通過公共的訪問方法來訪問
*/
private static LazySingleton instance=null;
/**
* 私有化構(gòu)造器,使之不能直接構(gòu)造對象
*/
private LazySingleton(){
}
/**
* 公共的提取對象的方法
* @return
*/
public synchronized static LazySingleton getInstance() {
if (instance==null) {
instance=new LazySingleton();
}
return instance;
}
}
餓漢式
餓漢式:與懶漢式相反,餓漢式就是在系統(tǒng)加載時就去創(chuàng)建類的實例。
demo如下:
package com.singleton;
/**
* 餓漢式
* @author xiang.wei
* @create 2018/4/10 10:34
*/
public class HungrySingleton {
private static final HungrySingleton SINGLETON = new HungrySingleton();
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return SINGLETON;
}
}
總結(jié):餓漢式與懶漢式相比要占用更多的內(nèi)存,因為系統(tǒng)加載之后就會創(chuàng)建實例。但是效率要比懶漢式要高。
雙重加鎖
雙重加鎖是懶漢式的一種擴(kuò)展。因為直接在getInstance()上加上synchronized會導(dǎo)致每次調(diào)用方法時都需要加鎖。執(zhí)行效率不高。所以,我們采用了雙重加鎖的方式。
package com.singleton;
/**
* 懶漢式
* 雙重加鎖
* @author xiang.wei
*/
public class LazySingleton_two {
/**
* 定義一個私有變量,目的是外部不能直接訪問該變量,必須通過公共的訪問方法來訪問
*/
private static volatile LazySingleton_two instance = null;
/**
* 私有化構(gòu)造器,使之不能直接構(gòu)造對象
*/
private LazySingleton_two() {
}
/**
* 公共的提取對象的方法
*
* @return
*/
public static LazySingleton_two getInstance() {
//如果單例存在則直接返回
if (instance == null) {
//單例不存在,則進(jìn)入同步代碼塊
synchronized (LazySingleton_two.class) {
if (instance == null) {
System.out.println("實例化的次數(shù)");
instance = new LazySingleton_two();
}
}
}
return instance;
}
}
雙重加鎖并不是加兩個synchronized關(guān)鍵字。
第一個判斷是當(dāng)對象存在時則直接返回實例,當(dāng)對象不存在時則進(jìn)入同步代碼塊中,同步代碼塊的作用跟之前是相同的,就是防止兩個線程同時訪問同步代碼塊的內(nèi)容,造成生成多個實例的情況。同步代碼塊每次只允許一個線程進(jìn)入,創(chuàng)建完實例后返回。第二個判斷是當(dāng)多個線程排隊進(jìn)入代碼塊時,第一個線程創(chuàng)建完實例返回后,第二個線程再進(jìn)入時,不需要在創(chuàng)建實例。
采用雙重加鎖后,代碼的執(zhí)行效率有了較大的提升。
靜態(tài)內(nèi)部類的方式
public class MySingleton {
private static class MySingletonHandle {
private static final MySingleton instance = new MySingleton();
}
private MySingleton() {
}
public MySingleton getSingleton() {
return MySingletonHandle.instance;
}
}
作者:碼農(nóng)飛哥
微信公眾號:碼農(nóng)飛哥