单例模式:
- 单例介绍
- 单例的六种写法和各自特点
饿汉、懒汉、懒汉安全、DCL、静态内部类、枚举。
- 单例的六种写法和各自特点
- android中的单例
application实例、
单例引起的内存泄露,EventBus异步实现库所造成的内存泄露以及解决办法
- android中的单例
1.单例介绍
1.概念
单例模式是一种对象创建模式,它用于产生一个对象的具体实例,它可以保证系统中一个类只产生一个实例。
java里头,单例概念是在虚拟机的范围内,装载类是在虚拟机中,ClassLoader装载实现单例类的时候,就会创建一个类的实例
2.好处
1.对于频繁使用的对象,可以省略创建对象所花费的时间,它对于那些重量级对象而言,是非常可观的一笔系统开销
2.由于new 操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间
写法:
1.私有静态对象
2.私有的构造方法
3.公共的静态的获取单例对象入口方法getInstance()
2.单例的六种写法和各自特点
饿汉、懒汉、懒汉线程安全、DCL、静态内部类、枚举。
饿汉:图。
无法对单例对象创建做延时加载。只要使用了这个类。比如类的静态方法,单例对象就会被创建,因为有static的成员变量
懒汉:图。 多线程中无法保证实例唯一,这样的实现是失效的
懒汉线程安全:
图。1.在getInstance方法外使用 synchronized
2.或者在方法内部锁住class
性能效率不足
DCL:双检查所机制:
public class DclSingleton{
private static DclSingleton mInstance = null;
private DclSingleton();
public static DclSingleton getInstance(){
//避免不需要的同步
if(mInstance == null){
synchronized(DclSingleton.class){
//在第一次调用时初始化
if(mIntance == null){
mInstance = new DclSingleton();//有改进的地方
}
}
}
return mInstance;
}
}
解决了 性能、线程安全问题。
待改进地方:mInstance = new DclSingleton();不是原子操作
JVM :1.分配内存 2.调用 构造方法初始化变量 3.将创建的对象指向我们分配的内存空间
JVM存在指令排序的优化,以上三个步骤可能不是依次执行的,而是乱序-->线程不安全
修改 private static volatile DclSingleton mInstance =null;//可见性
保证线程在本地不会存有mInstance的副本,每次都去内存中读取。更重要的原因是禁止JVM重排序的优化,也就是原有三步一定依次执行,不存在重排序的情况
解决了线程安全问题,也存在JVM的即时编译器中存在指令重排序的优化,禁止后缺少该优化
优化:静态内部类/枚举
1.主要原因。JVM提供的同步控制。 static 、final。 static进行区块的初始化数据,保证我们的数据在内存中是同一份。
final 字段初始化之后无法被修改
图:
public class StaticInnerSingleton{
private StaticInnerSingleton(){
}
public static StaticInnerSingleton getInstance(){
return SingletonHolder.sInstance;
}
//静态内部类 里头创建对象实例
;只要没有使用这个内部类,JVM就不会加载这个类,也就不会创建里面的单例对象。从而这里就完成了懒汉式的延时加载 。static又完成了线程安全
只有在调用了getInstance之后,java的虚拟机才会加载SingleHolder,并实例化instance
妙处:利用了类中静态变量的唯一性,同时JVM加载机制保证了线程安全,同时我们没有使用关键字同步,保证了性能 3.SingleHolder是私有的,外部无法使用,保证了安全
private static class SingletonHolder{
private static final StaticInnerSingleton mInstance = new StaticInnerSingleton();
}
}
3.android中的单例
application实例、
单例引起的内存泄露,EventBus异步实现库所造成的内存泄露以及解决办法
图
图
图
图
图
网友评论