1、飢餓模式
//飢餓模式 public final class Singleton { private static Singleton singObj = new Singleton(); private Singleton(){ } public static Singleton getSingleInstance(){ return singObj; } }
飢餓模式,每個對象在沒有使用之前就已經初始化了,有點資源浪費,同時也會加重系統啓動時的負擔;
2、懶漢模式
//懶漢模式 public final class Singleton { private static Singleton singObj = null; private Singleton(){ } public static Singleton getSingleInstance(){ if(null == singObj ){ singObj = new Singleton(); } return singObj; } }
懶漢模式解決了上面飢餓模式的未使用就加載的問題,只有在使用時才創建,相對來說更優一些,但是問題又來了,在高併發系統中,這兩種模式下創建單例對象是線程安全的嗎?答案顯而易見是否定的,那如何線程安全的創建單例對象呢?
3、線程安全的方式創建單例對象
public final class Singleton { private static Singleton singObj = null; private Singleton(){ } public static Synchronized Singleton getSingleInstance(){ if(null == singObj ){ singObj = new Singleton(); } return singObj; } }
在 getSingleInstance()方法上加上synchronized關鍵字的確可以解決線程安全的問題,但是使用synchronized關鍵字會阻塞線程,勢必會降低系統的併發性,有沒有更優雅的一種方式來實現呢?
4、優雅的支持高併發方式的單例
public class Singleton { private static class SingletonHolder { public final static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
這種方法使用內部類來做到延遲加載對象,在初始化這個內部類的時候,JLS(Java Language Sepcification)會保證這個類的線程安全。這種寫法最大的美在於,完全使用了Java虛擬機的機制進行同步保證,沒有一個同步的關鍵字。