单例模式
懒汉恶汉式
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public class Singleton {
private static Singleton instance =new Singleton();
private Singleton() {
}
public static synchronized Singleton getInstance() {
return instance;
}
}
Double Check Lock(DCL) 实现单例
public class Singleton {
private static Singleton sInstance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (sInstance == null) {
synchronized (Singleton.class) {
if (sInstance == null) {
sInstance = new Singleton();
}
}
}
return sInstance;
}
}
这种单例特点就是进行两次==null的判断,为什么这么写呢? 因为sInstance = new Singleton();
并是一个原子操作 虚拟机在执行这行代码的时候大概做了三件事情:
- 给Singleton的实例分配内存;
- 调用Singleon()的构造函数, 初始化成员字段;
将sInstance对象分配到制定内存空间 (此时的sInstanc 就不是null了)
由于在JDK1.5之前JVM执行第二第三部的时候顺序无法保证 所以有可能是
1-2-3, 也有可能是1-3-2,假如是按照1-2-3的顺序 这中DCL单例就很好 例如 :第一个线程执行完第一步第二步切换到第二个线程此时的sIntance是null的所以他会执行new Singleton();但是有个最大的缺点 : 假如第一个线程是按照1-3-2的顺序 第一个线程执行完1-3 第二个线程来了发现sInstance不是null的 , 就会拿去用 , 使用时就会
报错
静态内部类单例
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.sInstance;
}
/**
* 静态内部类
*/
private static class SingletonHolder {
private static final Singleton sInstance = new Singleton();
}
}
这种方式当调用getInstance的时候才会加载SingletonHolder类 这种方式不仅能够保证线程安全,也能保证对象唯一,同时也是延迟加载对的实例化
枚举单例
public class Singleton {
private static Singleton sInstance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (sInstance == null) {
synchronized (Singleton.class) {
if (sInstance == null) {
sInstance = new Singleton();
}
}
}
return sInstance;
}
}
这种单例我认为是最好的 写起来方便 而且项目用起来没啥问题 我们后台说他也很喜欢用这种单例他对这种单例进行了一些测试都没啥问题
使用容器实现单例
public class Singleton {
private static Map<String, Object> map = new HashMap<>();
private Singleton() {
}
public static void register(String key, Object instance) {
if (!map.containsKey(key)) {
map.put(key, instance);
}
}
public static Object getInstance(String key) {
return map.get(key);
}
}
这个其实是一个同意管理类,使用时根据key获取对应类型对象,使我们可以管理多种类型单例, 安卓系统中经常使用的WindowsManagerService,ActivityManagerService,以及非常常用的LayoutInflater类都是以这种方式来管理的