这是我在学习《Android源码设计模式解析和实战》过程中对单例模式作一个记录。方便以后随时翻看。
单例模式是应用最广泛的模式之一,使用的常见场景
: 网络请求,访问IO,数据库和线程池等很消耗资源的情况下,可以考虑使用单例模式。
中心原则就是:
- 确保单例类的对象有且只有一个,尤其是在多线程环境下。
- 确保反序列化的时候不会重新构建对象。
饿汉模式
单例实例在类装载时构建。将构造函数私有化,使得外部程序不得通过构造函数创建对象,只能通过静态方法返回一个唯一的静态对象。
public class Singleton{
private static final Singleton sInstance = new Singleton();
//构造函数私有化
private Singleton(){}
public static Singletoon getInstance() {
return sInstance;
}
}
懒汉模式
单例实例在第一次被调用时进行初始化。
懒汉模式的实现如下:
public class Singleton {
private static Singleton sInstance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (sInstance == null) {
sInstance = new Singleton();
}
return sInstance;
}
}
在获取单例对象的静态方法中添加了synchronized,这可以在多线程下保证单例对象的唯一性。
缺点
:
- 第一次加载需要进行实例化,反应稍慢。
- 每次调用getInstance()都要进行同步,造成了很多不必要的同步开销。
因此,一般不建议使用
懒汉模式。
基于volatile的双重检查锁(double-checked locking)
public class Singleton {
//private static Singleton sInstance = null;
//防止DCL失效问题,保证instance对象每次都是从住内存中读取
private static volatile Singleton sInstance = null;
private Singleton() {}
public static Singleton getInstance() {
//避免不必要的同步
if (sInstance == null) {
synchronized (Singleton.class) {
//在sInstance = null下创建实例
if (sInstance == null) {
sInstance = new Singleton();
}
}
}
return sInstance ;
}
}
缺点
:
- JDK1.5以上版本才有volatile。
优点
:
- 资源利用率高,第一次执行getInstance()时才会被实例化,效率高。
静态内部类单例模式
在《Java 并发编程实践》中提及了DCL失效的问题(上面基于volatile的双重检查锁例子中注释的部分),建议使用如下代码替换:
public class Singleton {
private Singleton() {}
public static Singleton getInstance() {
return SingletonHolder.sInstance;
}
private static class SingletonHolder {
private static final Singleton sInstance = new Singleton();
}
}
优点
:
- 资源利用率高,第一次执行getInstance()时才会被实例化,效率高。
- 不仅保证线程安全,而且也保证了单例对象的唯一性,同时也延迟了单例的实例化,所以这才是
推荐使用
的单例模式实现方式。
枚举单例
public class SingletonEnum {
INSTANCE;
public void doSomething() {
//do something;
}
}
优点
:
- 枚举在Java中于普通的类一样,可以有字段,方法。 默认枚举创建的实例是线程安全的。
- 使用enum实现的单例自带防序列化。
然而上述的几种单例模式实现中在反序列化时会重新创建对象。要杜绝单例对象重新生成对象,必须要加入如下方法:
private Object readResolve() throws ObjectStreamException {
return sInstance;
}
参考资料
- [1]《Android源码设计模式解析和实战》
- [2]《Java 并发编程实践》