說起設(shè)計模式袖扛,java中總共有23中設(shè)計模式,我們最常見的也就屬于單例設(shè)計模式了弯蚜,它也是最簡單的設(shè)計模式孔轴。
首先,什么是單例設(shè)計模式碎捺?? ? 單例設(shè)計模式是在程序運(yùn)行過程中路鹰,該程序中只能存在該類的一個對象。
單例設(shè)計模式書寫方法:1. 構(gòu)造方法私有化? ? 2. 提供靜態(tài)的方法供外部調(diào)用
單例設(shè)計模式的書寫方式有很多中收厨,比較常見的就是餓漢式和懶漢式晋柱。
餓漢式:
public class Singleton {
? ? private static Singleton mInstance = new Singleton();
? ? private Singleton() {
? ? }
? ? public static Singleton getInstance() {
? ? ? ? return mInstance;
? ? }
}
這種方式在類加載的時候就會創(chuàng)建對象,容易造成內(nèi)存浪費诵叁。執(zhí)行效率高趣斤,線程安全。
懶漢式:
public class Singleton {
private static SingletonmInstance =null;
? ? private Singleton() {
}
public static SingletongetInstance() {
if (mInstance ==null) {
mInstance =new Singleton();
? ? ? ? }
return mInstance;
? ? }
}
在調(diào)用的時候才會創(chuàng)建對象黎休,但是線程不安全浓领。多線程調(diào)用時會出現(xiàn)問題。
public class Singleton {
private static SingletonmInstance =null;
? ? private Singleton() {
}
public static SingletongetInstance() {
if (mInstance ==null) {
synchronized (Singleton.class) {
if (mInstance ==null) {
mInstance =new Singleton();
? ? ? ? ? ? ? ? }
}
}
return mInstance;
? ? }
}
在獲取對象時加上synchronized關(guān)鍵字势腮,能夠保證在多線程調(diào)用時不會出現(xiàn)線程安全問題联贩,但是相對來說效率較低。但這種方式并不完善捎拯,還是會極小概率出現(xiàn)問題泪幌。
由于java在創(chuàng)建對象時有以下三個步驟:
? ? 1. 開辟一塊內(nèi)存空間
? ? 2. 初始化對象
? ? 3. 將初始化好的對象指向內(nèi)存空間
然而這個執(zhí)行順序并非固定,有可能會按照1->2->3的順序執(zhí)行署照,也有可能會執(zhí)行1->3->2的順序祸泪。當(dāng)按照132順序執(zhí)行時,會導(dǎo)致對象未被初始化就指向了內(nèi)存空間建芙,從而出現(xiàn)問題没隘。此使使用volatile關(guān)鍵字,可以有效避免這個問題禁荸。
volatile關(guān)鍵字的作用主要有以下兩點:
? ? 1. 防止指令重排序
? ? 2. 保持內(nèi)存可見性
因此修改后的代碼如下:
public class Singleton {
private volatile static SingletonmInstance =null;
? ? private Singleton() {
}
public static SingletongetInstance() {
if (mInstance ==null) {
synchronized (Singleton.class) {
if (mInstance ==null) {
mInstance =new Singleton();
? ? ? ? ? ? ? ? }
}
}
return mInstance;
? ? }
}