單例模式應(yīng)該是設(shè)計模式中最好理解丧没,比較簡單的一種婚瓜。單例模式分為兩種 懶漢式和餓漢式兩编兄。
餓漢式是在程序編譯過程中就進行對象創(chuàng)建歼跟,后來的使用只是對對象調(diào)用和媳,所以不存在線程安全問題。
懶漢式
public class Singleton {
// 創(chuàng)建靜態(tài)實例化對象
private static final Singleton instance = new Singleton();
// 私有化構(gòu)造方法
private Singleton() {
}
// 提供靜態(tài)的對外的對象獲取方法
public static Singleton getInstance() {
return instance;
}
}
懶漢式是在使用的時候去判斷是否已經(jīng)生成對象哈街,如果是多線程的情況下留瞳,就會出現(xiàn)一種情況,線程1判斷完對象還是null準備實例化骚秦,線程2也進行了判斷而線程1還沒實例化完成斗導(dǎo)致的后果就是實例化了2次她倘,針對這種情況,要進行加鎖作箍。保證線程安全帝牡。
懶漢式單例加鎖
public class Singleton2 {
public static Singleton2 Singleton=null;
private Singleton2() {}
public synchronized static Singleton2 getInstance(){
if (Singleton==null) {
return Singleton=new Singleton2();
}
return Singleton;
}
}
保證了當(dāng)多個進程進入第一個判斷鎖時,會被同步機制隔離蒙揣,只有一個程序進入新建對象靶溜,再其他線程進入時,instance已經(jīng)不為null,因此不會新建多個對象罩息。但也有一個問題嗤详,就是java是實行無序?qū)懭氲臋C制,在某個線程執(zhí)行的過程中瓷炮,instance被賦予了地址葱色,但是singleton對象還沒構(gòu)造完成時,如果有線程訪問了此時判斷instance不為空娘香,但是方法返回的是一個不完整對象的引用苍狰。此時可能會產(chǎn)生錯誤!
懶漢式單例雙重加鎖
public class Singleton3 { //適用JDK1.5及以后
private volatile static Singleton3 instance;
private Singleton3() {
}
public static Singleton3 getInstance() {
if (instance == null) {
synchronized (Singleton3.class) {
if (instance == null) {
instance = new Singleton3();//由于不是原子操作,禁止指令重排序優(yōu)化,因此instance需要 volatile關(guān)鍵字修飾
}
}
}
return instance;
}
}
還有一種靜態(tài)內(nèi)部類的方式抹缕,這里采用靜態(tài)初始化的方式,它由JVM來保證線程安全性翔忽,當(dāng)類裝載的時候不去初始化對象,在這個內(nèi)部類中去實例化對象盏檐,因此只要不使用內(nèi)部類就不會創(chuàng)建對象歇式,這樣能解決線程安全的問題還可以實現(xiàn)延遲加載且不會增加任何訪問開銷
懶漢式單例靜態(tài)內(nèi)部
public class Singleton4 {
private Singleton4() {}
private static class SigletonHolder{
private static Singleton4 instance=new Singleton4();
}
public static Singleton4 getInstance(){
return SigletonHolder.instance;
}
}