單例模式屬于創(chuàng)建型模式的一種,應(yīng)用于保證一個(gè)類僅有一個(gè)實(shí)例的場(chǎng)景下擅羞,并且提供了一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)混狠,如spring中的全局訪問(wèn)點(diǎn)BeanFactory丽涩,spring下所有的bean都是單例桐腌。
單例模式的特點(diǎn):從系統(tǒng)啟動(dòng)到終止拄显,整個(gè)過(guò)程只會(huì)產(chǎn)生一個(gè)實(shí)例。
單例模式常用寫法:懶漢式案站,餓漢式邓馒,注冊(cè)式闪朱,序列化式槐秧。
下面比較一下懶漢式和餓漢式:
懶漢式:默認(rèn)不會(huì)實(shí)例化,什么時(shí)候用什么時(shí)候new遭殉。
public class Lazy{
????????private Lazy(){};
????????// 默認(rèn)不會(huì)實(shí)例化,什么時(shí)候用什么時(shí)候new
????????private static Lazy lazy = null;
????????public static synchronized Lazy getInstance(){
????????????????if (lazy == null) {
????????????????????????lazy = new Lazy();
????????????????}
????????????????return lazy;
????????}????
}
餓漢式:類加載的時(shí)候就實(shí)例化博助,并且創(chuàng)建單例對(duì)象险污。
public class Hungry{
????????private Hungry(){};
????????// 類加載的時(shí)候就實(shí)例化,并且創(chuàng)建單例對(duì)象
????????private static final Hungry hungry = new Hungry();
????????public static Hungry getInstance() {
????????????????return hungry;
????????}
}
懶漢式和餓漢式區(qū)別:
? ??實(shí)例化方面:懶漢式默認(rèn)不會(huì)實(shí)例化富岳,外部什么時(shí)候調(diào)用什么時(shí)候new蛔糯。餓漢式在類加載的時(shí)候就實(shí)例化,并且創(chuàng)建單例對(duì)象城瞎。
? ??線程安全方面:餓漢式線程安全 (在線程還沒(méi)出現(xiàn)之前就已經(jīng)實(shí)例化了渤闷,因此餓漢式線程一定是安全的)疾瓮。懶漢式線程不安全( 因?yàn)閼袧h式加載是在使用時(shí)才會(huì)去new 實(shí)例的脖镀,那么你去new的時(shí)候是一個(gè)動(dòng)態(tài)的過(guò)程,是放到方法中實(shí)現(xiàn)的狼电,比如:public static synchronized Lazy getInstance(){? ?if(lazy==null){??lazy=new Lazy(); } 如果這個(gè)時(shí)候有多個(gè)線程訪問(wèn)這個(gè)實(shí)例蜒灰,這個(gè)時(shí)候?qū)嵗€不存在,還在new肩碟,就會(huì)進(jìn)入到方法中强窖,有多少線程就會(huì)new出多少個(gè)實(shí)例。一個(gè)方法只能return一個(gè)實(shí)例削祈,那最終return出哪個(gè)呢翅溺?是不是會(huì)覆蓋很多new的實(shí)例?這種情況當(dāng)然也可以解決髓抑,那就是加同步鎖咙崎,避免這種情況發(fā)生) 。
? ??執(zhí)行效率上:餓漢式?jīng)]有加任何的鎖吨拍,因此執(zhí)行效率比較高褪猛。懶漢式一般使用都會(huì)加同步鎖,效率比餓漢式差羹饰。
? ??性能上:餓漢式在類加載的時(shí)候就初始化伊滋,不管你是否使用,它都實(shí)例化了队秩,所以會(huì)占據(jù)空間笑旺,浪費(fèi)內(nèi)存。懶漢式什么時(shí)候需要什么時(shí)候?qū)嵗勺剩鄬?duì)來(lái)說(shuō)不浪費(fèi)內(nèi)存燥撞。