单例模式的五种写法: 懒汉 恶汉 静态内部类 枚举 双重校验锁
1.懒汉
class LazySingleton{ PRivate static LazySingleton singleton; private LazySingleton(){ } public static LazySingleton getInstance(){ if(singleton==null){ singleton=new LazySingleton(); } return singleton; } }常用的写法。问题:没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例
2.饿汉
class HungrySingleton{ private static HungrySingleton singleton=new HungrySingleton(); private HungrySingleton(){} public static HungrySingleton getInstance(){ return singleton; }}在类初始化时,已经自行实例化,缺点:没有达到懒加载的效果
3.静态内部类
class InternalSingleton{ private static class SingletonHolder{ private final static InternalSingleton INSTANCE=new InternalSingleton(); } private InternalSingleton(){} public static InternalSingleton getInstance(){ return SingletonHolder.INSTANCE; }}优点:加载时不会初始化静态变量INSTANCE,因为没有主动使用,达到Lazy loading。既实现了线程安全,又避免了同步带来的性能影响
4.枚举
public enum Singleton { INSTANCE; private String name; public String getName(){ return name; } public void setName(String name){ this.name = name; }}《Effective java》作者推荐使用的方法,优点:不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。 虽然Effective Java中推荐使用,但是在Android平台上却是不被推荐的。在这篇Android Training中明确指出: Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.
5.双重校验锁
class LockSingleton{ private volatile static LockSingleton singleton; private LockSingleton(){} //详见:http://www.ibm.com/developerworks/cn/java/j-dcl.html public static LockSingleton getInstance(){ if(singleton==null){ synchronized(LockSingleton.class){ if(singleton==null){ singleton=new LockSingleton(); } } } return singleton; }}它在当前的内存模型中无效。 可以看到里面加了volatile关键字来声明单例对象。它有两层语义。 第一层,可见性。指的是在一个线程中对该变量的修改会马上由工作内存(Work Memory)写回主内存(Main Memory),所以会马上反应在其它线程的读取操作中。 第二层语义是禁止指令重排序优化。由于编译器优化,在实际执行的时候可能与我们编写的顺序不同。编译器只保证程序执行结果与源代码相同,却不保证实际指令的顺序与源代码相同。 既然已经起到了多线程下原子性、有序性、可见性的作用, 双重检测锁定失败的问题并不归咎于 JVM 中的实现 bug,而是归咎于 Java 平台内存模型。内存模型允许所谓的“无序写入”,这也是失败的一个主要原因。 还有疑问可参考http://www.iteye.com/topic/652440 和http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
参考: http://www.oschina.net/code/snippet_107039_6062 http://blog.csdn.net/jason0539/article/details/23297037 http://www.cnblogs.com/andy-zhou/p/5363585.html#_caption_5