單例模式:
乙個類只有乙個物件
單例模式包括:餓漢模式和懶漢模式
懶漢模式:
直到要用到例項時,才會去載入。時間換空間
缺點: 在多執行緒併發情況下,會產生多個例項化物件,出現執行緒安全問題
重新上傳
取消
餓漢模式:
一開始就載入好了,每次用到就直接返回
用空間換時間
重新上傳
取消
總結:1、單例模式類中的構造是private修飾的,防止外界同過new來建立例項
2、通過public static的方法返回乙個例項
3、單例只能有乙個例項
4、單例必須自己建立自己的唯一例項
單例的優點:
在記憶體裡只存在乙個例項,減小了記憶體的開銷,避免對資源的多重占用(比如寫檔案操作)。
單例的缺點:
沒有介面,不能繼承,與單一職責原則衝突,乙個類應該只關心內部邏輯,而不關心外部怎樣來例項化。
單例的使用場景:
1、要求生產唯一的序列號
2、web中的計數器,不用每次重新整理都在資料庫裡加一次,用單例先快取起來。
單執行緒下使用單例模式不會出現執行緒安全問題,但是在多執行緒環境下,就可能出現。所以就會有雙重校驗鎖
重新上傳
取消
第一次判斷singleton是否為null:
因為第一次判斷是在同步**塊外面進行的,單例模式要求的是只建立乙個例項,並且通過getinstances方法返回singleton物件。所以第一次判斷是為了防止已經建立了singleton物件的情況下還進入了同步**塊。這一次判斷是為了提示效率。
第二次判斷singleton是否為null
第二次判斷是為了:如果執行緒a經過第一次判斷,它是空的,然後它準備進入同步**塊。這時候執行緒b獲得了時間片,而a還沒有經過第二次判斷,所以a還沒有建立物件,所以singleton依然是空的,b得到時間片後,經過第一次判斷,進入同步**塊,也經過第二次判斷,然後成功建立了物件。然後a再次獲得時間片,它直接進入同步**塊,不會重複進行第一次判斷。這時,如果沒有第二次判斷,a就會直接建立singleton物件,這就不滿足我們單例模式的要求,就建立出了兩個物件,如果有第二判斷,a發現singleton不為空,所以就不能再建立物件。所以第二次判斷很有必要的。
為什麼加volatile關鍵字? (
volatile保證了執行緒的可見性和順序性。在這裡我們主要是利用它的順序性,保證jvm不會對指令重排序。
我們都知道建立乙個物件不是一步完成的,它分3個步驟。第一步是,獲得singleton物件的記憶體位址,第二步,初始化singleton物件,第三步,把這塊記憶體位址指向引用變數singleton。
其中第二部初始化操作和第三步指向引用之間是沒有依賴關係的,所以在jvm優化程式時,會進行指令重排序。可能在還沒有初始化,就讓記憶體位址指向了引用。這時通過getinstance方法獲得的物件可能會有錯,程式會報異常。所以加上volatile就能保證指令按順序執行,得到正確的物件。
單例模式(餓漢模式 懶漢模式)
餓漢單例模式 通過單例模式可以保證系統中,應用該模式的類乙個類只有乙個例項 即乙個類只有乙個物件例項 並提供乙個訪問它的全域性訪問點,該例項被所有程式模組共享。設計模式 一書中給出了一種很不錯的實現,定義乙個單例類,使用類的私有靜態指標變數指向類的唯一例項,並用乙個公有的靜態方法獲取該例項。分點表述...
單例模式 餓漢模式 懶漢模式
構造方法私有化 靜態屬性指向例項 public static的 getinstance方法,返回第二步的靜態屬性 餓漢式是立即載入的方式,無論是否會用到這個物件,都會載入。如果在構造方法裡寫了效能消耗較大,佔時較久的 比如建立與資料庫的連線,那麼就會在啟動的時候感覺稍微有些卡頓。懶漢式,是延遲載入的...
懶漢餓漢單例模式
懶漢式單例類,在第一次呼叫時的時候例項化自己 public class singleton private static singleton single null 靜態工廠方法 public static singleton getinstance return single 執行緒安全的懶漢式單...