武昌網(wǎng)站建設(shè)推廣手段和渠道有哪些
目錄
1.什么是單例模式:
2.單例模式存在的原因:
3.單例模式的優(yōu)缺點(diǎn):
4.創(chuàng)建方式:
1. 單線程單例模式立即創(chuàng)建(餓漢式):
??????????2. 單線程單例模式延遲創(chuàng)建(懶漢式):
5.多線程下測(cè)試兩種模式存在哪些問(wèn)題
1.先測(cè)試餓漢式,代碼如下:
2.測(cè)試懶漢式,修改 run 方法創(chuàng)建對(duì)象
6.兩種模式簡(jiǎn)單對(duì)比:
7.其他的單例模式:
1.什么是單例模式:
單例模式(Singleton Pattern)是 Java 中最簡(jiǎn)單的設(shè)計(jì)模式之一。這種類(lèi)型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。
這種模式涉及到一個(gè)單一的類(lèi),該類(lèi)負(fù)責(zé)創(chuàng)建自己的對(duì)象,同時(shí)確保只有單個(gè)對(duì)象被創(chuàng)建。這個(gè)類(lèi)提供了一種訪問(wèn)其唯一的對(duì)象的方式,可以直接訪問(wèn),不需要實(shí)例化該類(lèi)的對(duì)象。
注意:
- 1、單例類(lèi)只能有一個(gè)實(shí)例。
- 2、單例類(lèi)必須自己創(chuàng)建自己的唯一實(shí)例。
- 3、單例類(lèi)必須給所有其他對(duì)象提供這一實(shí)例。
2.單例模式存在的原因:
一些對(duì)象的存在只需要唯一的一個(gè),例如,緩存池和線程池。如果線程池存在多例的話,會(huì)導(dǎo)致資
源使用過(guò)量,緩存多個(gè)的話,會(huì)導(dǎo)致數(shù)據(jù)不一致
3.單例模式的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
- 在內(nèi)存中只有一個(gè)對(duì)象,節(jié)省內(nèi)存空間
- 避免頻繁的創(chuàng)建銷(xiāo)毀對(duì)象,可以提高性能
- 避免對(duì)共享資源的多重占用,簡(jiǎn)化訪問(wèn)
- 為整個(gè)系統(tǒng)提供一個(gè)全局訪問(wèn)點(diǎn)
缺點(diǎn):
- 沒(méi)有接口,不能繼承,
- 與單一職責(zé)原則沖突,一個(gè)類(lèi)應(yīng)該只關(guān)心內(nèi)部邏輯,而不關(guān)心外面怎么樣來(lái)實(shí)例化
注意事項(xiàng):getInstance() 方法中需要使用同步鎖 synchronized (Singleton.class) 防止多線程同時(shí)進(jìn)入造成 instance 被多次實(shí)例化。
4.創(chuàng)建方式:
創(chuàng)建一個(gè) maven 項(xiàng)目 singleton
1. 單線程單例模式立即創(chuàng)建(餓漢式):
創(chuàng)建類(lèi)cn.xs.singleton.Hunchback
public class Hunchback {/* 創(chuàng)建唯一一個(gè)單例對(duì)象 */private static Hunchback singleton = new Hunchback();/*** 不能讓外界直接創(chuàng)建對(duì)象,所以設(shè)置私有構(gòu)造器*/private Hunchback() {}/*** 單例對(duì)象的全局訪問(wèn)點(diǎn)** @return*/public static Hunchback getInstance() {return singleton;}
}
2. 單線程單例模式延遲創(chuàng)建(懶漢式):
在創(chuàng)建類(lèi) cn.xs.singleton.Lazybones
public class Lazybones {/* 創(chuàng)建唯一一個(gè)單例對(duì)象 */private static Lazybones singleton = null;/*** 不能讓外界直接創(chuàng)建對(duì)象,所以設(shè)置私有構(gòu)造器*/private Lazybones() {}/*** 單例對(duì)象的全局訪問(wèn)點(diǎn)** @return*/public static Lazybones getInstance() {if (singleton == null) {singleton = new Lazybones();}return singleton;}
}
5.多線程下測(cè)試兩種模式存在哪些問(wèn)題
新建測(cè)試類(lèi) cn.xs.singleton.SingletonTest
1.先測(cè)試餓漢式,代碼如下:
public class SingletonTest extends Thread {@Overridepublic void run() {Hunchback singleton = Hunchback.getInstance();System.out.println(singleton);}/*** 測(cè)試方法** @param args*/public static void main(String[] args) {for (int i = 0; i < 10; i++) {SingletonTest singletonTest = new SingletonTest();singletonTest.start();}}
}
輸出的都是同一個(gè)對(duì)象,沒(méi)有線程安全問(wèn)題,但是不能延遲加載
2.測(cè)試懶漢式,修改 run 方法創(chuàng)建對(duì)象
@Override
public void run() {Lazybones singleton = Lazybones.getInstance();System.out.println(singleton);
}
控制臺(tái)輸出了兩個(gè)對(duì)象,可見(jiàn),懶漢式存在線程安全問(wèn)題
解決方式一:
在方法上加上 synchronized,保證對(duì)臨界資源的同步互斥訪問(wèn)
/**
* 單例對(duì)象的全局訪問(wèn)點(diǎn)
*
* @return
*/
public synchronized static Lazybones getInstance() {if (singleton == null) {singleton = new Lazybones();}return singleton;
}
這種方式雖然解決了問(wèn)題,但是當(dāng)有線程在執(zhí)行方法時(shí),不管有沒(méi)有創(chuàng)建對(duì)象,其他線程都會(huì)在外等候里面的線程執(zhí)行完畢,有沒(méi)有一種方式可以解決這個(gè)問(wèn)題,提高代碼執(zhí)行效率
解決方式二:
在方法中創(chuàng)建對(duì)象部分設(shè)置同步塊
public static Lazybones getInstance() {if (singleton == null) {synchronized (Lazybones.class) {if (singleton == null) {singleton = new Lazybones();}}}return singleton;
}
分析:當(dāng)還沒(méi)有創(chuàng)建對(duì)象的時(shí)候,如果被多個(gè)線程同時(shí)進(jìn)入方法執(zhí)行,比如線程 1,線程 2 進(jìn)來(lái)執(zhí)行方法,兩個(gè)線程同時(shí)判斷外層 if 時(shí),都為 true ,都進(jìn)入外層 if 執(zhí)行,當(dāng)走到同步塊時(shí),比如線程 1 進(jìn)入同步塊執(zhí)行代碼,線程 2 只能在外面等著,當(dāng)線程 1 創(chuàng)建完對(duì)象執(zhí)行完同步塊后,線程 2 再進(jìn)入同步塊執(zhí)行代碼,在同步塊中,線程 2 判斷內(nèi)層 if ,結(jié)果為 false ,不用再創(chuàng)建對(duì)象,再有別的線程來(lái)執(zhí)行方法,就不會(huì)再一直等待前一個(gè)線程了,因?yàn)橥鈱?if 已經(jīng)永遠(yuǎn)為 false 。
6.兩種模式簡(jiǎn)單對(duì)比:
餓漢式:線程安全,調(diào)用率高,但是不能延遲加載懶漢式:線程安全,調(diào)用率不高,可以延遲加載
7.其他的單例模式:
雙重檢測(cè)鎖式(由于JVM底層內(nèi)部模型原因,偶爾會(huì)出問(wèn)題,不建議使用)
靜態(tài)內(nèi)部類(lèi)式(線程安全,調(diào)用效率高。但是,可以延時(shí)加載)
枚舉式(線程安全,調(diào)用率高,不能延時(shí)加載)
對(duì)比五種模式,如何選用?單例對(duì)象占用資源少,不需要延遲加載,枚舉式比餓漢式好單例對(duì)象占用資源大,需要延遲加載,靜態(tài)內(nèi)部類(lèi)式比懶漢式好