解法一:只適合單線程環(huán)境(不好)
/**
* @author xiaoping
* */
public class Singleton {
private static Singleton instance=null;
private Singleton(){
}
public static Singleton getInstance(){ if(instance==null){
instance=new Singleton();
} return instance;
}
}
注解:Singleton的靜態(tài)屬性instance中撬讽,只有instance為null的時候才創(chuàng)建一個實(shí)例,構(gòu)造函數(shù)私有悬垃,確保每次都只創(chuàng)建一個游昼,避免重復(fù)創(chuàng)建。
缺點(diǎn):只在單線程的情況下正常運(yùn)行盗忱,在多線程的情況下酱床,就會出問題。例如:當(dāng)兩個線程同時運(yùn)行到判斷instance是否為空的if語句趟佃,并且instance確實(shí)沒有創(chuàng)建好時扇谣,那么兩個線程都會創(chuàng)建一個實(shí)例。
解法二:多線程的情況可以用闲昭。(懶漢式罐寨,不好)
public class Singleton {
private static Singleton instance=null;
private Singleton(){
}
public static synchronized Singleton getInstance(){ if(instance==null){
instance=new Singleton();
} return instance;
}
}
注解:在解法一的基礎(chǔ)上加上了同步鎖,使得在多線程的情況下可以用序矩。例如:當(dāng)兩個線程同時想創(chuàng)建實(shí)例鸯绿,由于在一個時刻只有一個線程能得到同步鎖,當(dāng)?shù)谝粋€線程加上鎖以后簸淀,第二個線程只能等待瓶蝴。第一個線程發(fā)現(xiàn)實(shí)例沒有創(chuàng)建,創(chuàng)建之租幕。第一個線程釋放同步鎖舷手,第二個線程才可以加上同步鎖,執(zhí)行下面的代碼劲绪。由于第一個線程已經(jīng)創(chuàng)建了實(shí)例男窟,所以第二個線程不需要創(chuàng)建實(shí)例盆赤。保證在多線程的環(huán)境下也只有一個實(shí)例。
缺點(diǎn):每次通過getInstance方法得到singleton實(shí)例的時候都有一個試圖去獲取同步鎖的過程歉眷。而眾所周知牺六,加鎖是很耗時的。能避免則避免汗捡。
解法三:加同步鎖時淑际,前后兩次判斷實(shí)例是否存在(可行)
public class Singleton {
private static Singleton instance=null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance=new Singleton();
}
}
} return instance;
}
}
注解:只有當(dāng)instance為null時,需要獲取同步鎖凉唐,創(chuàng)建一次實(shí)例庸追。當(dāng)實(shí)例被創(chuàng)建,則無需試圖加鎖台囱。
缺點(diǎn):用雙重if判斷淡溯,復(fù)雜,容易出錯簿训。
解法四:餓漢式(建議使用)
public class Singleton {
private static Singleton instance=new Singleton();
private Singleton(){
}
public static Singleton getInstance(){ return instance;
}
}
注解:初試化靜態(tài)的instance創(chuàng)建一次咱娶。如果我們在Singleton類里面寫一個靜態(tài)的方法不需要創(chuàng)建實(shí)例,它仍然會早早的創(chuàng)建一次實(shí)例强品。而降低內(nèi)存的使用率膘侮。
缺點(diǎn):沒有l(wèi)azy loading的效果,從而降低內(nèi)存的使用率的榛。
解法五:靜態(tài)內(nèi)部內(nèi)琼了。(建議使用)
public class Singleton {
private Singleton(){
}
private static class SingletonHolder{
private final static Singleton instance=new Singleton();
}
public static Singleton getInstance(){ return SingletonHolder.instance;
}
}
注解:定義一個私有的內(nèi)部類,在第一次用這個嵌套類時夫晌,會創(chuàng)建一個實(shí)例雕薪。而類型為SingletonHolder的類,只有在Singleton.getInstance()中調(diào)用晓淀,由于私有的屬性所袁,他人無法使用SingleHolder,不調(diào)用Singleton.getInstance()就不會創(chuàng)建實(shí)例凶掰。
優(yōu)點(diǎn):達(dá)到了lazy loading的效果燥爷,即按需創(chuàng)建實(shí)例。