当前位置: 首页 > news >正文

Android 设计模式--单例模式

一,定义 

单例模式就是确保某一个类只有一个实例,而且自行实例化,并向整个系统提供这个实例

二,使用场景

确保某个类只有一个对象的使用场景,避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个。例如,创建一个对象需要消耗过多的资源,如要访问IO和数据库等资源,就应该考虑单例模式了。

三,饿汉式单例

/*** 饿汉式单例模式* */
public class YuanZhen {private static final YuanZhen yuanzhen =new YuanZhen();private YuanZhen(){}public static YuanZhen getInstance(){return yuanzhen;}}

饿汉式优点: 不需要加锁,性能优越

饿汉式缺点:一开始就加载好了对象,占用内存

四,懒汉式单例

/*** 懒汉式单例* */
public class YuanZhen1 {private  static YuanZhen1 yuanZhen1;private YuanZhen1(){}public static synchronized YuanZhen1 getInstance(){if(yuanZhen1 ==null){yuanZhen1 =new YuanZhen1();}return yuanZhen1;}
}

懒汉式单例就是在需要的时候去创建对象。

懒汉式单例的优点:单例只有在使用的时候才去加载,一定程度上节约了资源

懒汉式单例的缺点:

1.第一次加载时需要实例化,运行稍慢

2.每次调用synchronized同步锁,消耗资源

3,虽然加了同步锁,但是仍然可能会出现同步问题

五,DCL 双重锁检查机制实现单例模式

/*** DCL单例* */
public class YuanZhen2 {private static YuanZhen2 yuanZhen2;private YuanZhen2(){}public static  YuanZhen2 getInstance(){if(yuanZhen2 == null){synchronized (YuanZhen2.class){if(yuanZhen2 ==null){yuanZhen2 =new YuanZhen2();}}}return yuanZhen2;}
}

在getInstance方法中,对yuanzhen2进行了2次判空,第一次判空是为了避免不必要的同步

第二次判空是为了在null的情况下创建实例

当线程A执行到new Yuanzhen2() 这句代码时,它最终会被编译成多条汇编指令:

1,给YuanZhen2的实例分配内存

2,调用YuanZhen2的构造函数,初始化成员变量

3,将yuanzhen2对象指向分配的内存空间

JDK1.5之前,它们在内存中的执行顺序可能1-2-3 也可能是1-3-2.

如果是1-3-2,那么如果执行完3之后,切换到了B线程,那这时yuanzhen2表面上看是非空,实际上是空的。那么后面再使用的时候就会报错,这就是DCL失效。

但是JDK1.5之后,调整了JVM.只需要将YuanZhen2的定义改成如下volatile方式,就能保证YuanZhen2对象每次都是从主内存中读取。

/*** DCL单例* */
public class YuanZhen2 {private static volatile YuanZhen2 yuanZhen2;private YuanZhen2(){}public static  YuanZhen2 getInstance(){if(yuanZhen2 == null){synchronized (YuanZhen2.class){if(yuanZhen2 ==null){yuanZhen2 =new YuanZhen2();}}}return yuanZhen2;}
}

volatile会影响性能,但是如果可以避免DCL的失效问题,这点性能几乎可以忽略不计了

DCL的优点:

1,资源利用率高,第一次执行getInstance时单例对象才被初始化

2,避免了多余的同步问题

3,避免了线程的并发问题

DCL的缺点:

1,第一次加载时反省稍慢

2,使用synchronized 和 volaile 关键字,性能有一定消耗

六,静态内部类实现单例

/*** 静态内部类* */
public class YuanZhen3 {private YuanZhen3(){}public static YuanZhen3 getInstance(){return SingletonHolder.yuanzhen3;}private static class SingletonHolder{private static final YuanZhen3 yuanzhen3 =new YuanZhen3();}
}

当第一次加载YuanZhen3类时,并不会初始化yuanzhen3,只有在第一次调用Yuanzhen3的getInstance方法时才会导致yuanzhen3被初始化,因此,第一次调用getInstance方法会导致虚拟机加载SingletonHolder类,这种方式不仅能确保线程安全,也能够保证单例对象的唯一性,同时也延迟了单列的实例化,所以这是最推荐使用的方式。

七,枚举实现单例

/*** 枚举方式* */
public enum YuanZhen4 {INSTACE;
}

枚举方式是最简单的单例实现方式。而且它也是线程安全的,并且在任何情况下它都是一个单例。

在上述几种方式中,我们可以通过hook反序列化的函数readResolve来重新生成对象,除非我们重写readResolve函数将对象返回。但是枚举并不存在这个问题

八,使用容器实现单例

/*** 使用容器* */
public class YuanZhen5 {private static Map<String,Object> map =new HashMap<>();private YuanZhen5(){}public static void registerInstance(String key,Object instance){if(!map.containsKey(key)){map.put(key, instance);}}public static Object getInstance(String key){return map.get(key);}
}

使用:

YuanZhen5.registerInstance("1", YuanZhen1.getInstance());
YuanZhen5.registerInstance("2", YuanZhen2.getInstance());
YuanZhen2 yuanzhen2 = (YuanZhen2) YuanZhen5.getInstance("2");

在程序初始化时将多种单例类型注入到一个统一的管理类中,在使用时根据key获取对应类型的单例。

优点:

1,方便管理多种类型的单例

2,使用时可以通过统一的接口进行获取操作,降低了用户的使用成本

3,对用户隐藏了具体实现

4,降低了耦合度

九,总结

单例模式优点:

1,单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁的创建,销毁时,单例模式的优势就非常明显了

2,由于单例模式只生成一个实例,所以,减少了系统的性能开销,当一个对象的创建需要比较多的资源时,则可以通过在应用启动时直接产生一个单例对象,然后用永久驻留内存的方式来解决。

缺点:

1,单例模式一般没有接口,扩展很难

2,单例对象如果持有context,很容易发生内存泄漏,此时需要注意,传递给单例对象的Context最好是Application Context。

http://www.lryc.cn/news/226457.html

相关文章:

  • 语音识别与自然语言处理(NLP):技术前沿与未来趋势
  • k8s-docker二进制(1.28)的搭建
  • 【代码随想录】算法训练计划18
  • Leetcode刷题详解—— 组合总和
  • Echarts柱状体实现滚动条动态滚动
  • SplayTree高分测试用例
  • 制作麒麟V10-server-sp2镜像
  • 2.docker镜像的导入导出
  • bs4介绍和遍历文档树、搜索文档树、案例:爬美女图片、 bs4其它用法、css选择器
  • 微服务-开篇-个人对微服务的理解
  • 机器学习算法-集成学习
  • LINUX入门篇【4】开发篇--开发工具vim的使用
  • 代码随想录算法训练营Day 50 || 309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费
  • 【C语言】【数据结构】【环形链表判断是否带环并返回进环节点】有数学推导加图解
  • 漏洞扫描-nuclei-poc编写
  • SpringBoot 自动配置
  • IP-guard WebServer 远程命令执行漏洞
  • 每次重启完IDEA,application.properties文件里的中文变成?
  • 【Truffle】四、通过Ganache部署连接
  • React 其他常用Hooks
  • 将 ONLYOFFICE 文档编辑器与 С# 群件平台集成
  • 使用电脑时提示msvcp140.dll丢失的5个解决方法
  • VR全景如何应用在房产行业,VR看房有哪些优势
  • 11月份 四川汽车托运报价已经上线
  • springcloud图书借阅管理系统源码
  • 主题模型LDA教程:LDA主题数选取:困惑度preplexing
  • Docker快速入门
  • 36 Gateway网关 快速入门
  • MyBatis的知识点和简单用法
  • KITTI数据集(.bin数据)转换为点云数据(.pcd文件)