本文主要根据以下著作中的内容整理而来:
何红辉,关爱民.Android源码设计模式解析与实践第2版〔M〕.北京:人民邮电出版社,2017.7
定义
确保某一个类只有一个实例,自行实例化并向整个系统提供这个实例。
角色
Client——高层客户端。
Singleton——单例类。
特点
私有:构造方法是私有的,静态变量是私有的。
静态:通过一个公有的静态方法或枚举返回单例类对象。
线程安全:多线程环境下也要确保对象只有一个。
几种实现方式
以下几种方式在初始化静态对象上有不同。
饿汉模式:声明静态对象时直接初始化。new的过程很耗时的话,应用程序启动的会很慢,降低体验的友好性
懒汉模式:声明一个静态对象,在用户第一次调用getInstance()时初始化。延迟单例的实例化。
懒汉模式 问题:getInstance的调用频率很高的话,每次都synchronized同步访问,效率低。
双重检查锁定(DCL):既能在需要时初始化,又能保证线程安全,消除懒汉模式中重复同步问题。(得比较多的方式,JDK1.5及以上版本使用volatile,没有复杂的并发场景下一般能满足使用)
静态内部类:解决双重检查锁定失效问题。(推荐使用的实现方式)
代码示例
双重检查锁定方式:
public class Singleton{
//问题1:new操作的反汇编代码,其实他包含3条汇编指令:new、dup、init。sInstance 不为null并不保证sInstance是完整地初始化好了成员。
// 问题2:即使一个线程实例化了sInstance ,由于每个线程都有自己的working缓存,可能另一个线程看不到前一个线程对sInstance 的操作。
// JDK1.5及以后 使用volatile关键字,保证每次sInstance都是从主内存中获取。
private volatile static Single sInstance = null;
private Singleton(){}
public static Singleton getInstance(){
if(sInstance==null){
synchronize(Singleton.class){
if(sInstance==null){
sInstance = new Singleton();//实际上不是一个原子操作:1.给Singleton实例分配内存;2.调用Singleton()构造方法初始化成员字段;3.将sInstance指向分配的内存空间。 执行顺序可能是1-2-3或者1-2-3。
}
}
}
}
}
静态内部类方式:
public class Singleton{
private Singleton(){}
public static Singleton getInstance(){
// 延迟初始化
return SingletonHolder.sInstance;
}
private static class SingletonHolder{
//静态变量是线程共享的,保证了单例的线程安全。避免了双重检查锁定失效问题。
private static final Singleton sInstance = new Singleton();
}
}
扩展应用
使用容器实现单例
Android Context的实现类ContextImpl
public class ContextImpl extends Context {
private final static Map<String,ServiceFetcher> SYSTEM_SERVICE_MAP= new HashMap<String,ServiceFetcher>();
public static void registerService(String serviceName,ServiceFetcher fetcher){
//省略代码
SYSTEM_SERVICE_MAP.put(serviceName,fetcher);
}
public Object getSystemService(String key){
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(key);
return fetcher ==null? null:fetcher.getService(this)
}
static {
registerService(LAYOUT_INFLATER_SERVICE,new ServiceFetcher(){
public Object createService(ContextImpl ctx){
return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
}
})
}
}
网友评论