單例模式在java中的定義:一個(gè)類有且僅有一個(gè)實(shí)例,并且自行實(shí)例化向整個(gè)系統(tǒng)提供。在單例模式中要注意兩點(diǎn),
- 構(gòu)造方法私有并不能保證客戶端不能創(chuàng)建對(duì)象,客戶端可以通過(guò)java反射機(jī)制實(shí)例化對(duì)象,防止這種情況的辦法就是在構(gòu)造器中設(shè)置一個(gè)sentinel,保證只實(shí)例化一次,再次實(shí)例化拋出RuntimeException異常。
- 單例模式要考慮多線程下的情形,考慮在實(shí)例化對(duì)象的代碼塊上同步
下面給出幾種實(shí)現(xiàn)單例模式的方法:
餓漢式單例模式,加載類的時(shí)候?qū)嵗瘜?duì)象
public class EargeSingle {
private static boolean sentinel= false;
private static final EargeSingle eargeSingle = new EargeSingle();
private EargeSingle(){
if(!sentinel){
sentinel = true;
}else{
throw new RuntimeException("已經(jīng)實(shí)例化了");
}
}
public static EargeSingle getInstance(){
return eargeSingle;
}
}-
嵌套類的方式,jvm加載類初始化靜態(tài)域是線程安全的。這個(gè)可以說(shuō)是完美的單例模式,既延遲初始化,又不使用額外的同步
public class NestedSingleton {
private static class Holder{
private static NestedSingleton singleton = new NestedSingleton();
}
//不再重復(fù)寫防止客戶端實(shí)例化對(duì)象
private NestedSingleton(){}public static NestedSingleton getInstance(){ return Holder.singleton; } }
-
同步延遲加載方式,也就是雙重檢查的方式,但是由于重排序的問(wèn)題,需要在實(shí)例變量加上volatile關(guān)鍵字,表示一個(gè)線程的對(duì)對(duì)象的修改會(huì)立即通知其他的線程。
public class SynchronizeSingleton { private static volatile SynchronizeSingleton singleton; private SynchronizeSingleton(){} public static SynchronizeSingleton getInstance(){ if(singleton == null){ create(); } return singleton; } private synchronized static void create() { if(singleton == null){ singleton = new SynchronizeSingleton(); } } }