1、時間和空間
比較上面兩種寫法:懶漢式是典型的時間換空間,也就是每次獲取例項都會進行判斷,看是否需要建立例項,浪費判斷的時間。當然,如果一直沒有人使用的話,那就不會建立例項,則節約記憶體空間。
餓漢式是典型的空間換時間,當類裝載的時候就會建立類例項,不管你用不用,先建立出來,然後每次呼叫的時候,就不需要再判斷了,節省了執行時間。
2、執行緒安全
(1)從執行緒安全性上講,不加同步的懶漢式是執行緒不安全的,比如,有兩個執行緒,乙個是執行緒a,乙個是執行緒b,它們同時呼叫getinstance方法,那就可能導致併發問題。如下示例:
public static singleton getinstance()return instance; }
程式繼續執行,兩個執行緒都向前走了一步,如下:
public static singleton getinstance()return instance; }
可能有些朋友會覺得文字描述還是不夠直觀,再來畫個圖說明一下,如圖5.4所示。
圖5.4 懶漢式單例的執行緒問題示意圖
通過圖5.4的分解描述,明顯地看出,當a、b執行緒併發的情況下,會建立出兩個例項來,也就是單例的控制在併發情況下失效了。
(2)餓漢式是執行緒安全的,因為虛擬機器保證只會裝載一次,在裝載類的時候是不會發生併發的。
(3)如何實現懶漢式的執行緒安全呢?
當然懶漢式也是可以實現執行緒安全的,只要加上synchronized即可,如下:
public static synchronized singleton getinstance(){}但是這樣一來,會降低整個訪問的速度,而且每次都要判斷。那麼有沒有更好的方式來實現呢?
(4)雙重檢查加鎖
可以使用"雙重檢查加鎖"的方式來實現,就可以既實現執行緒安全,又能夠使效能不受到很大的影響。那麼什麼是"雙重檢查加鎖"機制呢?
所謂雙重檢查加鎖機制,指的是:並不是每次進入getinstance方法都需要同步,而是先不同步,進入方法過後,先檢查例項是否存在,如果不存在才進入下面的同步塊,這是第一重檢查。進入同步塊過後,再次檢查例項是否存在,如果不存在,就在同步的情況下建立乙個例項,這是第二重檢查。這樣一來,就只需要同步一次了,從而減少了多次在同步情況下進行判斷所浪費的時間。
雙重檢查加鎖機制的實現會使用乙個關鍵字volatile,它的意思是:被volatile修飾的變數的值,將不會被本地執行緒快取,所有對該變數的讀寫都是直接操作共享記憶體,從而確保多個執行緒能正確的處理該變數。
看看**可能會更加清楚些。示例**如下:
public class singletonpublic static singleton getinstance()
} }
return instance;
} }
這種實現方式可以實現既執行緒安全地建立例項,而又不會對效能造成太大的影響。它只是在第一次建立例項的時候同步,以後就不需要同步了,從而加快了執行速度。
懶漢式單例和餓漢式單例優缺點
1 時間和空間 比較上面兩種寫法 懶漢式是典型的時間換空間,也就是每次獲取例項都會進行判斷,看是否需要建立例項,浪費判斷的時間。當然,如果一直沒有人使用的話,那就不會建立例項,則節約記憶體空間。餓漢式是典型的空間換時間,當類裝載的時候就會建立類例項,不管你用不用,先建立出來,然後每次呼叫的時候,就不...
餓漢式單例和懶漢式單例
當我們想要乙個類只產生乙個例項化物件時,就需要用到單例模式,單例設計模式分為兩種 餓漢式和懶漢式。1 餓漢式單例 當用到這個類時,不管是否需要乙個物件都會建立乙個例項化物件 public class singleton public static singleton getinstance publ...
單例(懶漢式單例 餓漢式單例)
public class singleton private static singleton instance new singleton public static singleton getinstance public class singleton public static synchr...