簡介:單例模式是設計模式中使用比較廣泛的設計模式,也是很是簡單的一種設計模式。單例模式是指確保系統中只有一個實例。最多見的單例模式分爲懶漢模式和餓漢模式。java
1. 單例模式的好處:設計模式
1)對於頻繁使用的對象,能夠省去建立對象的開銷;多線程
2)因爲new操做的次數減小,於是對系統內存的使用頻率也會下降,從而減小系統GC的時間。性能
2. 單例模式造成的條件優化
1)必需要有一個私有構造器spa
2)單例對象變量須要是私有的靜態static線程
3. 餓漢模式( 這個漢子太餓了,一上來就直接new 對象實例)設計
實現代碼:code
SingletonDemoHungry.java對象
/** * <p>Description: 單例模式 * 餓漢模式 * </p> * @author Huang Xiaocong * @data 2019年10月27日 */ public class SingletonDemoHungry { private SingletonDemoHungry() { //私有構造器 System.out.println("建立單例模式"); //實際開發中,建立單例模式的時候可能比較慢 } private static SingletonDemoHungry instance = new SingletonDemoHungry(); public static SingletonDemoHungry getInstance() { return instance; } }
優勢:這種單例模式的實現方式簡單可靠。
缺點:沒法對對象實例(instance)作延遲加載。假如在單例的建立過程很慢,而因爲instance成員變量是static定義的,因此在加載單例類的過程當中也會一塊兒加載。若單例類中還存在其餘static方法或者變量,也會一塊兒加載。而且在其餘地方使用該單例類時也會被加載屢次。
如SingletonDemoHungry.java單例類中還存在其餘靜態方法:
public static void printInfo() { System.out.println("printInfo in SingletonDemoHungry!!"); }
在其餘地方調用SingletonDemoHungry.printInfo(); 時, 程序將打印以下信息。程序並無使用單例類,但instance實例仍是被建立出來了。
建立單例模式
printInfo in SingletonDemoHungry!!
爲了解決上述這個問題,可使用餓漢模式。
4.懶漢模式(這個漢子太懶了,直到要使用的時候才new 對象)
SingletonDemoLazy.java
/** * <p>Description: 懶漢模式</p> * @author Huang Xiaocong * @data 2019年10月27日 */ public class SingletonDemoLazy { private static SingletonDemoLazy instance = null; private SingletonDemoLazy() { System.out.println("建立單例模式"); //實際開發中,建立單例模式的時候可能比較慢 } public static synchronized SingletonDemoLazy getInstance() { if(instance == null) { instance = new SingletonDemoLazy(); } return instance; } }
該懶漢模式與餓漢模式相比,引入了延遲加載機制。但其中的getInstance()方法必須是同步的,不然在多線程環境下,當線程1在新建單例時,建立完正打算賦值時,線程2可能判斷instance爲null,同時進行建立對象,而致使多個實例被建立。雖然實現了延遲加載的功能,可是同時又引入了新的問題,使用synchronized關鍵字,在多線程環境中,它的時耗遠遠大於餓漢模式。
爲了使用延遲加載反而下降了系統性能,得不償失,可對其進行改進優化:
/** * <p>Description: 改進的懶漢模式</p> * @author Huang Xiaocong * @data 2019年10月27日 */ public class SingletonDemoNewLazy { private SingletonDemoNewLazy() { System.out.println("SingletonDemoNewLazy.SingletonDemoNewLazy()"); } //內部類SingletonHolder private static class SingletonHolder { private static SingletonDemoNewLazy instance = new SingletonDemoNewLazy(); } public static SingletonDemoNewLazy getInstance() { return SingletonHolder.instance; } }
改進後的單例模式使用內部類維護單例類的實例,當SingletonDemoNewLazy被加載時,其內部類並不會被初始化。而只有當調用getInstance()方法時纔會調用加載SingletonHolder。即最後的SingletonDemoNewLazy.java既實現了延遲加載,也沒必要使用同步機制。