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