在这章正式进入设计模式的学习
每次看的时候都是枯燥无味的希望这次编写博客便让自己的理解更加深刻或者多一点乐趣吧
(1) 单例模式
这是我们最常用的一张模式,也有可能是有的人唯一会得设计模式
(2)单例的生命周期
在android端单例的生命周期和application的生命周期相同,在单进程的应用中我们甚至可以使用单例作为数据传输的一种方式。
但是在不同的进程之间是不能使用单例是失效的
(3)定义
确保类只用一个实例,而且自行实例化并向整个系统提供实例
(4)还有现在这个感觉有时候UML视图比写的代码都重要
所以下次有的模式我们可以不必要记住具体是实现 只记一张UML就可以了,我们要具备的事吧UML转换为代码的能力感觉这样应该会明显的加快我们的学习效率。
先来看看我们的UML视图
(5) 构建单例的关键点
1.私有构造方法
2.通过一个静态方法或枚举返回单例对象
3.确保单例只有一个,尤其是在多线程的情况下
4.确保单例在反序列化是不会重新构建对象
(6)单例对象学习关键点 一定要能手写两个最全的,一定要能手写两个最全的,
一定要能手写两个最全的。只要能达到面试基本就带达标了
第一个(懒汉)+双重校验
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
这里面我们要了解的知识
volatile :使用这个字段是为了保持 newSingleton()的原子性
简单说以下一个类的创建过程
1.给Test的实例分配内存
2.初始化Test的构造器
3.将instance对象指向分配的内存空间(注意 此时instance就不为空)
Java编译器允许处理器乱序执行,在创建的过程中不一定是按照1-2-3执行的有可能是1-3-2
并且在3执行完毕、2未执行之前,被切换到线程二上,这时候instance因为已经在线程一内执行过了第三点,instance已经是非空了,所以线程二直接拿走instance,然后使用,然后顺理成章地报错。
synchronized :确保只有一个线程在进行实例化操作。
为什么要两次判空
(1)第一次判空,理论上是可以去掉的,去除之后并不影响单例的正确性,但是去除之后效率低。因为去掉之后,不管instance是否已经初始化,都会进行synchronized操作,而synchronized是一个重操作消耗性能。加上之后,如果已经初始化直接返回结果,不会进行synchronized操作
(2)二个判空条件是不可以去除,如果去除了,并且刚好有两个线程a和b都通过了第一个判空条件。此时假设a先获得锁,进入synchronized的代码块,初始化instance,a释放锁。接着b获得锁,进入synchronized的代码块,也直接初始化instance,instance被初始化多遍不符合单例模式的要求~。加上第二个判空条件之后,b获得锁进入synchronized的代码块,此时instance不为空,不执行初始化操作。
第二个(恶汉)
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}