單例模式即一個 JVM 內存中只存在一個類的對象實例。java
類加載的時候就建立實例面試
使用的時候才建立實例後端
固然還有其餘的生成單例的方式,雙重校驗鎖,枚舉和靜態內部類,文中會有介紹。安全
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
線程不安全,不可用。多線程
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
同步方法,線程安全,效率低,不推薦。架構
public class Singleton { private static Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { singleton = new Singleton(); } } return singleton; } }
線程不安全,會產生多個實例,不可用。工具
無線程安全問題,不能延遲加載,影響系統性能。性能
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
public class Singleton { private static Singleton instance = null; static { instance = new Singleton(); } private Singleton (){} public static Singleton getInstance() { return instance; } }
public class Singleton { private static volatile Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
雙重校驗鎖,線程安全,推薦使用。spa
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
靜態內部類,線程安全,主動調用時才實例化,延遲加載效率高,推薦使用。線程
public enum Singleton { INSTANCE; public void whateverMethod() { } }
一、考慮多線程問題
二、單例類構造方法要設置爲private類型禁止外界new建立
private Singleton() {}
三、若是類可序列化,考慮反序列化生成多個實例問題,解決方案以下
private Object readResolve() throws ObjectStreamException { // instead of the object we're on, return the class variable INSTANCE return INSTANCE; }
枚舉類型,無線程安全問題,避免反序列華建立新的實例,不多使用。
一、工具類對象
二、系統中只能存在一個實例的類
三、建立頻繁或又耗時耗資源且又常常用到的對象
下面是單例模式在JDK的應用
另外,Spring 容器中的實例默認是單例餓漢式類型的,即容器啓動時就實例化 bean 到容器中,固然也能夠設置懶漢式 defalut-lazy-init="true"
爲延遲實例化,用到時再實例化。
推薦去個人博客閱讀更多:
2.Spring MVC、Spring Boot、Spring Cloud 系列教程
3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程
生活很美好,明天見~