参考1:http://en.wikipedia.org/wiki/Singleton_pattern#The_enum_way
参考2:http://devbean.blog.51cto.com/448512/203501/
单例模式指的是一个类被限制只能实例化成一个对象。实现单例模式的方式有5种,Java5.0之后最好的方式是第5种。
1.双重校验锁(Lazy initialization)
这种方式使用了双重锁检测(double-checkedlocking)来进行,java5.0之前不应该使用,因为有许多bugs。这样设计的问题在于在多线程访问过程中有可能构造函数执行之前(实例化尚未完成)实例就返回了,即返回null(参考2有讲为什么)。
public classSingletonDemo {
private static volatile SingletonDemo instance = null;
private SingletonDemo() {
}
public static SingletonDemogetInstance() {
if (instance == null) {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo();
}
}
}
return instance;
}
}
2.final初始化(Eager initialization)
这种模式使用了final关键字,优势是不需要对方法getInstance()声明synchronize,也没有额外的对象锁。
public classSingleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance(){
return INSTANCE;
}
}
3.静态块初始化(Static block initialization)
与上一种相比把类实例化放在了静态代码段中执行,加入了异常判断。
public classSingleton {
private static final Singleton instance;
static {
try {
instance = new Singleton();
}catch(Exception e) {
throw new RuntimeException("Darn, an error occurred!", e);
}
}
public static Singleton getInstance(){
return instance;
}
private Singleton() {
// ...
}
}
4.静态内部类方法(Initialization-on-demand holder idiom)
这种方法使用静态内部类来实现对象的单例模式,方法具有普遍性,可以在各种java版本、编译器、JVM上运行良好,是不需要特殊条件的线程安全的方法。
public classSingleton {
// Private constructor prevents instantiation from otherclasses
private Singleton() {
}
/**
* SingletonHolder is loaded on the firstexecution of
* Singleton.getInstance() or the first accessto SingletonHolder.INSTANCE,
* not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
}
5. enum声明(The enum way)
参考3: http://segmentfault.com/q/1010000000646806
《EffectiveJava》的作者Joshua Bloch在书中声称"a single-element enum type is the best way to implement asingleton"。这种方式获得单例是利用了任何enum类型的对象都只初始化一次,是线程安全的,还能防止反序列化重新创建新的对象,而且可以防止反射攻击。当然,这样做稍微有点不是那么灵活。
public enum Singleton3 {
INSTANCE;
private void execute() {
// Perform operation here
}
}