大家都知道单例模式有饿汉式和懒汉式,他们的优缺点和使用这里就不在介绍了,这篇文章主要是介绍在开发中推荐使用的几种模式,觉的不错请点赞,表示鼓励
一、Double Check Lock(DCL)实现单例
private static BaseApplication mInstance = null; //将构造进行私有化,这样就不能new这个对象,保证对象的单一性 private BaseApplication(){} public static BaseApplication getInstance(){ //确保对象没有没实例化,加这层判断是为了防止,每次获取对象的时候都进行线程锁 if(mInstance == null){ //防止多个线程同时创建这个对象 synchronized (BaseApplication.class){ //线程进来时,判断是否有对象,保证对象的单一性 if(mInstance == null){ mInstance = new BaseApplication(); } } } return mInstance; }
DCL :
既能够在需要时才能初始化单例,又能够保证线程安全,且单例对象初始化后调用getInstance不进行同步锁
优点:资源利用率高,第一次执行getInstance时单例对象才会被实例化,效率高
缺点:第一次加载时反应慢,也由于java内存模型的原因偶尔会失败,这个问题被称为双重检查锁定失效
二、静态内部类实现单例模式
//将构造进行私有化,这样就不能new这个对象,保证对象的单一性 private BaseApplication(){} public static BaseApplication getInstance(){ return BaseApplicationHolder.mInstance; } /** * 静态内部类 */ private static class BaseApplicationHolder{ private static final BaseApplication mInstance = new BaseApplication(); }
当第一次加载BaseApplication类时并不会初始化mInstance,只有在第一次调用getInstance方法时才会导致mInstance被初始化,因此,第一调用getInstance方法会导致虚拟机加载BaseApplicationHolder类,这种方式不仅能够确保线程安全,也能保证单例对象的唯一性,同时也延迟了单例的实例化
三、使用容器实现单例模式
//使用容器实现单例模式,一般项目用不到 private static Map<String , Object> objMap = new HashMap<>(); //将构造进行私有化,这样就不能new这个对象,保证对象的单一性 private BaseApplication(){} public static void saveInstance(String key , Object instance){ if(!objMap.containsKey(key)){ objMap.put(key , instance); } } public static Object getInstance( String key){ return objMap.get(key); }
在程序的初始化,将多种单例类型注入到一个统一的管理类中,使用key获取对象对应类型的对象,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度
总结:以上三种单例模式的实现,前两项是推荐使用的实现,前两个有一个共同的缺点就是在反序列化的时候他们会出现重新创建对象的情况,第三个容器实现单例模式,在一般的开发中是使用不到的,具体的使用决定于项目本身