定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式的七种实现方式:
1.饿汉式
public class SingleInstance {
private static SingleInstance mInstance = new SingleInstance();
private SingleInstance() {}
public static SingleInstance getInstance() {
return mInstance;
}
}
2.懒汉式--线程不安全
public class SingleInstance {
private static SingleInstance mInstance;
private SingleInstance() {}
public static SingleInstance getInstance() {
if (mInstance == null) {
mInstance = new SingleInstance();
}
return mInstance;
}
}
3.懒汉式--线程安全
public class SingleInstance {
private static SingleInstance mInstance;
private SingleInstance() {}
public static synchronized SingleInstance getInstance() {
if (mInstance == null) {
mInstance = new SingleInstance();
}
return mInstance;
}
}
优点:懒汉式的优点是只有在使用时才会被实例化,在一定程度上节约了资源;
缺点:每次调用getInstance()
都要同步,造成不必要的同步开销;
4.Double Check Lock(DCL)双重校验锁,线程安全
public class SingleInstance {
private static SingleInstance mInstance;
private SingleInstance() {}
public static SingleInstance getInstance() {
if (mInstance == null) {
synchronized (SingleInstance.class) {
if (mInstance == null) {
mInstance = new SingleInstance();
}
}
}
return mInstance;
}
}
在getInstance()
方法中对mInstance
进行了两次判空:
第一层判断主要是为了避免不必要的同步;
第二层判断是为了在null的情况下创建实例;
优点:资源利用率高,第一次执行getInstance()
的单例对象才会被实例化,效率高;
缺点:第一次加载反应稍慢,由于Java内存模型的原因偶尔会失败。在高并发环境下也有一定的缺陷,虽然发生的概率很小;
5.使用静态内部类的方式
public class SingleInstance {
private SingleInstance() {}
/**
* 静态内部类
*/
private static class SingleInstanceHolder {
private static SingleInstance mInstance = new SingleInstance();
}
public static SingleInstance getInstance() {
return SingleInstanceHolder.mInstance;
}
}
当第一次加载SingleInstance
类时不会初始化mInstance
,只有在第一次调用SingleInstance
的getInstance()
方法时才会导致mInstance
被初始化。因此,第一次调用getInstance()
方法会导致虚拟机加载SingleInstanceHolder
类,这种方式不仅能保证线程安全,也能够保证单例对象的唯一性,同时也延迟了单例的实例化。
6.枚举单例
public enum SingleEnum {
INSTANCE;
public void doSomething() {
System.out.println("do somth");
}
}
在上述几种单例的实现方式中,如果将对象实例进行序列化,就会出现重新创建对象实例的情况。而对应枚举不会存在这个问题,因为即使反序列化它也不会重新生成新的实例。
7.使用容器实现单例模式
public class SingleManager {
private static Map<String, Object> objMap = new HashMap<>();
private SingleManager() {}
public static void registerService(String key, Object instance) {
if (!objMap.containsKey(instance)) {
objMap.put(key, instance);
}
}
public static Object getService(String key) {
return objMap.get(key);
}
}
在程序的初始,将多种单例类型注入到一个统一的管理类中,在使用是根据key获取对象对应的类型的对象。这中方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体的实现,降低耦合度。
网友评论