1. 程式人生 > >Java設計模式之Singleton——四種不同的單例模式(Singleton)

Java設計模式之Singleton——四種不同的單例模式(Singleton)

單例模式(Singleton [?sglt?n])

如果要保證系統裡最多隻能存在一個例項時,我們就需要單例模式。例如快取池、資料庫連線池等。

例項一:最簡單的單例模式

因為JVM在載入類時,對於static屬性的初始化只能由一個執行緒執行且僅執行一次,並且return操作是原子性的,所以,該方式是執行緒安全的。

例項二:延遲建立的單例模式(出於效能等方面的考慮)

延遲建立:在呼叫方法的時候建立例項,而不是在類載入的時候建立,這樣可以提高效能。 雖然延遲建立的方式可以提高效能,但是,它不是執行緒安全的。因為可能存在多個執行緒同時訪問程式碼塊:

這樣就會建立多個DelayBuildSingleton例項。為了解決這個問題,

雅思託福我們可以宣告getInstance()方法是synchronized的。但是在高併發訪問的情況下,給這個方法加上Synchronized關鍵字會使得效能大不如前。為了解決這些問題,我們可以使用Double-Check Locking方式。

例項三:Double-Check Locking

不瞭解volatile以及synchronized相關知識的,推薦先閱讀《Thining in Java》併發章節。 volatile關鍵字保證了instance的可視性,synchronized程式碼塊保證了例項化操作的原子性。他們一起協作,使得該方法是執行緒安全的。(關於volatile關鍵字,推薦一篇詳解部落格:http://www.importnew.com/18126.html) 該方式同時保證了執行緒安全和延遲建立。還有一種方式同樣可以達到此目的:

例項四:使用靜態私有內部類

只有在第一次呼叫getInstance()方法時,JVM才會載入LazyHolder類,並初始化靜態變數instance,這實現了延遲載入。同例項1一樣,該方式是執行緒安全的。

上面介紹了四種單例模式的實現方式。具體使用時,我們應該根據具體上下文環境來選擇。比如,在多執行緒環境下,應該選用執行緒安全的方式,如例項一、三、四。當效能需要優化時,則考慮例項二、例項四。通常情況下,例項四是推薦的方式,因為它同時滿足了效能和執行緒安全,同時代碼也並不複雜。