android开发几种常用单例分析

一、饿汉式

写法一:
在这里插入图片描述
写法二:
在这里插入图片描述
两种写法都是在类加载的时候就加载了实例,没有达到Lazy Loading的效果。
优点
1、写法简单
2、能够解决线程同步的问题
缺点
由于在类加载的时候就申请了一块内存,如果一直没有用到这个实例,就会导致内存的浪费。

二、懒汉式

写法一:
在这里插入图片描述
缺点:线程不安全,比如两个线程同时访问这个方法,就会导致创建两次对象,拿到的实例对象不一样,违背了单例的原则。

写法二:
在这里插入图片描述
在方法上加上线程锁synchronized。这样能够解决线程安全的问题。
缺点:效率比较低。当我们每次获取对象的时候,方法都要进行一次同步,同步需要耗时的,显然降低了效率。

写法三:
在这里插入图片描述
改用同步代码块的方式代替上面的方法同步,效率提上来了。
缺点:线程不安全。比如,当线程1进入if判断instance=null,还没有来得及进行下一次的if的判断,线程2也进来了,判断instace还是为null,这样就会实例化多个实例。(简而言之就是多个线程同时通过了if的判断,就会实例化多个对象)

三、双重检验

写法一:
在这里插入图片描述
第一层校验:判断当前对象是否被实例化,如果已经被实例化直接返回,这个过程没有加锁
第二层检验:再次判断对象是否已经实例化,否则实例化对象,这个过程加锁。

这样貌似能够解决线程安全的问题,但一定是能够放心使用的吗?当然不能,问题的关键就在于 “instance=new SingletonTwo” 这一行。首先需要了解对象的创建过程。对象正常的初始化顺序是:

在这里插入图片描述
但是有时候编译器为了性能的考虑,会将第二步和第三步进行调换,如下:
在这里插入图片描述
这样就导致了重排序的问题。

比如:线程A在实例化的过程中,线程B访问这个方法,就会判断instance是不为空的,就会返回使用,但实际上instance还没有实例化。导致空指针的出现。
缺点:编译器优化导致重排序问题,会出现空指针的情况。

写法二:
在这里插入图片描述
在上面的基础上增加了volatile修饰符,这样使用了volatile关键字后,重排序被禁止,不允许线程内部缓存,所有的写(write)操作都将发生在读(read)操作之前。

四、静态内部类

在这里插入图片描述
在饿汉式基础之上进行改良,这样能够实现线程安全(因为java虚拟机的静态内部类绝对是线程安全的)和Lazy Loading效果。只有第一次调用getInstance()方法的时候才会实例化对象,下次在调用不会再实例化。当getInstance()方法被调用时,SingletonIstance才在SingletonFour的运行时常量池里,把符号引用替换为直接引用,这时静态对象INSTANCE也真正被创建。
final
1、被修饰的变量只能初始化一次,保证了唯一性
2、java虚拟机编译后,是不会保留final属性的,这是因为虚拟机进行了优化处理。

缺点:传参是一个致命的问题

五、枚举类

在这里插入图片描述
使用如下:
在这里插入图片描述
借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。可能是因为枚举在JDK1.5中才添加,所以在实际项目开发中,很少见人这么写过。枚举为什么是单例的呢?下面分析一下,通过查看编译器编译的字节码问价,截图如下:
在这里插入图片描述

注意两点:
1、编译成字节码后继承自Enum类
2、编译成字节码后字段被加上static final修饰。
由于Enum的构造方法是私有的,所以一个枚举对象只能被实例化一次,另外由于被final修饰,也只能被初始化一次,线程安全的。

优点:系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
缺点:当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new,可能会给其他开发人员造成困扰,特别是看不到源码的时候。
适用场合

  1. 需要频繁的进行创建和销毁的对象;
  2. 创建对象时耗时过多或耗费资源过多,但又经常用到的对象;
  3. 工具类对象;
  4. 频繁访问数据库或文件的对象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值