单例(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();
}
}
这里也是一个使用 enum
的 Singleton 实现(只包含一个元素):
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 单例示例。