1)餓漢式:
instance作爲類變量,並且直接得到了初始化,類被主動使用時會完成實例的創建
缺點:如果instance被創建很久沒有被使用,會在堆內存中留駐很久,如果成員是很重的資源,則不建議使用
總結:可以保證多線程下的唯一實例,getInstance方法性能也比較高,但是無法進行懶加載
2)懶漢式
調用getInstance時,如果instance==null進行創建,在多線程環境下,不能保證instance實例的唯一性
3)懶漢式+同步方法
getInstance方法加synchronized修飾,既能保證實例唯一性,又是懶加載
缺點:由於synchronized排他性,getInstance方法同時只能一個線程訪問,性能低下
4)Double-check
首次初始化的時候加鎖,之後則允許多線程同時進行訪問getInstance方法獲得類的實例
缺點:可能會導致空指針異常,因爲jvm的指令重排序,instance返回的時候該類還有其他成員變量未完成實例化
5)volatile+Double-check
關鍵字volatile修飾instance來防止指令重排序
6)內部類Holder+volatile方式
將靜態成員變量instance放到靜態內部類Holder中,Holder被主動引用時就會創建instance,該實例的創建過程在java程序編譯時收集 到clinit方法中,該方法又是同步方法,可以保證實例的唯一性,單例設計中最好的設計之一,也是使用比較廣的設計之一
7)枚舉方式
利用了枚舉不能被繼承、線程安全的特性,推薦使用方式之一