單例(Java)

Java 中的單例與 C#非常相似,因為兩種語言都是物件導向的。下面是一個單例類的示例,其中只有一個版本的物件可以在程式的生命週期記憶體活(假設程式在一個執行緒上工作)

public class SingletonExample {

    private SingletonExample() { }

    private static SingletonExample _instance;

    public static SingletonExample getInstance() {

        if (_instance == null) {
            _instance = new SingletonExample();
        }
        return _instance;
    }
}

這是該程式的執行緒安全版本:

public class SingletonThreadSafeExample {

    private SingletonThreadSafeExample () { }

    private static volatile SingletonThreadSafeExample _instance;

    public static SingletonThreadSafeExample getInstance() {
        if (_instance == null) {
                createInstance();
        }
        return _instance;
    }

    private static void createInstance() {
        synchronized(SingletonThreadSafeExample.class) {
            if (_instance == null) {
                _instance = new SingletonThreadSafeExample();
            }
        }
    }
}

Java 還有一個名為 ThreadLocal 的物件,它以執行緒為基礎線上程上建立物件的單個例項。這在每個執行緒都需要自己的物件版本的應用程式中非常有用

public class SingletonThreadLocalExample {

    private SingletonThreadLocalExample () { }

    private static ThreadLocal<SingletonThreadLocalExample> _instance = new ThreadLocal<SingletonThreadLocalExample>();

    public static SingletonThreadLocalExample getInstance() {
        if (_instance.get() == null) {
            _instance.set(new SingletonThreadLocalExample());
        }
        return _instance.get();
    }
}

這裡也是一個使用 enumSingleton 實現(只包含一個元素):

public enum SingletonEnum {
    INSTANCE;
    // fields, methods
}

任何 Enum 類實現都確保每個元素只存在一個例項。

Bill Pugh Singleton 模式

Bill Pugh Singleton Pattern 是 Singleton 類使用最廣泛的方法,因為它不需要同步

public class SingletonExample {

    private SingletonExample(){}
    
    private static class SingletonHolder{
        private static final SingletonExample INSTANCE = new SingletonExample();
    }
    
    public static SingletonExample getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

使用私有內部靜態類,持有者不會載入到記憶體,直到有人呼叫 getInstance 方法。Bill Pugh 解決方案是執行緒安全的,不需要同步。

Java 文件標記下的 Singletons 主題中有更多 Java 單例示例。