单例如果考虑性能问题, 一般会选择懒汉式延迟加载
这里记录一下线程安全的单例写法
- 写法一: DCL
public class MySingleton {
private static volatile MySingleton sInstance; // 防止指令乱序
private MySingleton() {}
public static MySingleton getInstance() {
if (sInstance == null) { // 锁外校验, 削弱加锁导致的性能问题
synchronized (MySingleton.class) {
if (sInstance == null) { // 锁中校验, 确保只产生一个对象
sInstance = new MySingleton();
}
}
}
return sInstance;
}
}
- 写法二: Holder
public class MySingleton {
private MySingleton() {}
private static class SingletonHolder { // 静态类"主动使用"时才加载, 不同于饿汉式
private static final MySingleton INSTANCE = new MySingleton();
// 相当于加锁双重验证 = final保证初始化完成 , static保证单例;
}
public static MySingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
不论是哪种单例模式,其实例始终同Application共存亡,务必需注意其内部持有的监听或回调(addXxx,registXxx)造成的内存泄露
- 采用软/弱引用避免这种泄露
- 在合适的时机清除监听(如onDestroy)