安卓开发笔记 之 单例
Double Check
public class Singleton {
private static volatile Singleton singleton = null;
private Singleton() {
}
public static Singleton getSingleton() {
if (singleton == null) { // 尽量避免重复进入同步块
synchronized (Singleton.class) { // 同步 .class,意味着对同步类方法调用
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
- 如果两个线程竞争同一把锁,无非是排队执行还是会初始化两次,因此里面再加一次为空判断
- 为什么用 volatile? 原理
- 保证内存可见性
- 禁止指令重排序(happens-before 原则)
- 在 JVM 底层 volatile 是采用 内存屏障 来实现的
这里一定注意: volatile 关键字, 为什么必须要有
- 使用静态内部类
public class Singleton {
private Singleton(){}
public static Singleton getSingleton(){
return Holder.singleton;
}
private static class Holder {
private static Singleton singleton = new Singleton();
}
}
- 利用了静态对象初始化过程中隐含的初始化锁,和 Double Check 异曲同工。
- 静态内部类的优点是:外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化 INSTANCE,故而不占内存
- 通过反射,是不能从外部类获取内部类的属性的。内部类是 static 的,上面的
this$0
是有限制的,静态内部类和静态方法里面的内部类是没有this$0
这个引用的,因为静态内部类,是面向类的而不是对象,能够独自的应用本身,而脱离外部类,和外部类没有这个引用关系。 - 虚拟机会保证一个类的
<clinit>()
方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的<clinit>()
方法,其他线程都需要阻塞等待,直到活动线程执行<clinit>()
方法完毕。 详见类加载部分 - 分析
- 缺点
- 不能传参
- 一旦销毁就不能重新创建
Android 中的使用
context.getSystemService,跨进程与系统服务通信
Context 的两个子类分工明确,其中 ContextImpl 是 Context 的具体实现类,ContextWrapper 是 Context 的包装类。Activity, Application,Service 虽都继承自 ContextWrapper(Activity 继承自 ContextWrapper 的子类 ContextThemeWrapper),但它们初始 化的过程中都会创建 ContextImpl 对象,由 ContextImpl 实现 Context 中的方法。
// 系统服务容器
private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP = new HashMap<String, ServiceFetcher>();
// 注册服务
private static void registerService(String serviceName, ServiceFetcher fetcher) {
if (!(fetcher instanceof StaticServiceFetcher)) {
fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
}
SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
}
// 根据 key 获取对应的服务
@Override
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
下一篇: MyBatis 介绍和使用
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论