1. 程式人生 > >Java小白如何初步掌握java設計模式之單例模式!

Java小白如何初步掌握java設計模式之單例模式!

單例設計模式(Singleton Pattern)是最簡單且常見的設計模式之一,主要作用是提供一個全域性訪問且只例項化一次的物件,避免多例項物件的情況下引起邏輯性錯誤(例項化數量可控)…

概述

Java中,單例模式主要分三種:懶漢式單例、餓漢式單例、登記式單例三種。

Java小白如何初步掌握java設計模式之單例模式!

特點

Java小白如何初步掌握java設計模式之單例模式!

案例

Java小白如何初步掌握java設計模式之單例模式!

小編是一個有著5年工作經驗的java程式設計師,對於java,自己有做資料的整合,一個完整學習java的路線,學習資料和工具,相信這裡有很多學習java的小夥伴,我創立了一個2000人學習扣群,479121291。每晚都有java的直播課程。無論是初級還是進階的小夥伴小編我都歡迎!

注意事項

Java小白如何初步掌握java設計模式之單例模式!

解鎖姿勢

第一種:單一檢查(懶漢)非執行緒安全

Java小白如何初步掌握java設計模式之單例模式!

Java小白如何初步掌握java設計模式之單例模式!

日誌

Java小白如何初步掌握java設計模式之單例模式!

分析: 在單執行緒環境一切正常,balancer1和balancer2兩個物件的hashCode一模一樣,由此可以判斷出堆疊中只有一份內容,不過該程式碼塊中存線上程安全隱患,因為缺乏競爭條件,多執行緒環境資源競爭的時候就顯得不太樂觀了,請看上文程式碼註釋內容

第二種:無腦上鎖(懶漢)執行緒安全,效能較差,第一種升級版

Java小白如何初步掌握java設計模式之單例模式!

分析: 毫無疑問,知道synchronized關鍵字的都知道,同步方法在鎖沒釋放之前,其它執行緒都在排隊候著呢,想不安全都不行啊,但在安全的同時,效能方面就顯得短板了,我就初始化一次,你丫的每次來都上個鎖,不累的嗎(沒關係,它是為了第三種做鋪墊的)..

第三種:雙重檢查鎖(DCL),完全就是前兩種的結合體啊,有木有,只是將同步方法升級成了同步程式碼塊

Java小白如何初步掌握java設計模式之單例模式!

1.假設new LazyLoadBalancer()載入內容過多

2.因重排而導致loadBalancer提前不為空

3.正好被其它執行緒觀察到物件非空直接返回使用

Java小白如何初步掌握java設計模式之單例模式!

存在問題: 首先我們一定要清楚,DCL是不能保證執行緒安全的,稍微瞭解過JVM的就清楚,對比C/C++它始終缺少一個正式的記憶體模型,所以為了提升效能,它還會做一次指令重排操作,這個時候就會導致loadBalancer提前不為空,正好被其它執行緒觀察到物件非空直接返回使用(但實際還有部分內容沒載入完成)

解決方案: 用volatile修飾loadBalancer,因為volatile修飾的成員變數可以確保多個執行緒都能夠順序處理,它會遮蔽JVM指令重排帶來的效能優化。

第四種:Demand Holder (懶漢)執行緒安全,推薦使用

Java小白如何初步掌握java設計模式之單例模式!

分析: 在Demand Holder中,我們在LazyLoadBalancer裡增加一個靜態(static)內部類,在該內部類中建立單例物件,再將該單例物件通過getInstance()方法返回給外部使用,由於靜態單例物件沒有作為LazyLoadBalancer的成員變數直接例項化,類載入時並不會例項化LoadBalancerHolder,因此既可以實現延遲載入,又可以保證執行緒安全,不影響系統性能(居家旅行必備良藥啊)

第五種:列舉特性(懶漢)執行緒安全,推薦使用

Java小白如何初步掌握java設計模式之單例模式!

分析: 相比上一種,該方式同樣是用到了JAVA特性:列舉類保證只有一個例項(即使使用反射機制也無法多次例項化一個列舉量)

第六種:餓漢單例(天生執行緒安全),

Java小白如何初步掌握java設計模式之單例模式!

分析: 利用ClassLoad機制,在載入時進行例項化,同時靜態方法只在編譯期間執行一次初始化,也就只有一個物件。使用的時候已被初始化完畢可以直接呼叫,但是相比懶漢模式,它在使用的時候速度最快,但這玩意就像自己挖的坑哭著也得跳,你不用也得初始化一份在記憶體中佔個坑…

Java小白如何初步掌握java設計模式之單例模式!