程序员总要有一颗进阶的心,最近几日看一下Glide,Retrofit 源码解析,巴拉巴拉,看的有些疲劳,有些也是云里雾里,发现对源码的剖析还得从设计模式学起,不然连个Builder模式不懂,就在看人家的代码,也会理解的不深刻,当然这篇文章只是我的总结,有问题或者更专业的解答,可以留言。
文章将以关键字的形式进行,方便大家理解
单例关键词
-
一个对象
-
线程安全
-
延迟加载(懒加载)
-
效率
好了,单例的关键词就是这么多,面试时如果被问到就照着这四方面回答就行了,这四个点的概念就不多赘述了,大家自行百度吧。
饿汉式
public class Singleton {
private Singleton() {} //私有化构造器
private static Singleton instance = new Singleton(); // 加载类时立刻生成一个对象
public static Singleton getInstance() { //调用实例
return instance;
}
}
这个就是一个饿汉式的单例,首先是一个对象,单例中都是使用私有化构造器来实现一个对象这个条件,如果要new一个对象,就会报错;
第二,三点感觉可以放在一起说,首先是一调用这个类,他就会立即生成一个实例,这也相对应的失去延迟加载,所以这个类就显的它非常的饿,就像你开自助餐的,你一说哪个菜烧好了,饿汉他不管有没有自己盘子里有没有菜,都要来再加,这就会引起不必要的浪费(程序上也是这样),然后是线程安全,就一句话,加载类时,天然线程是安全的。
第四点,效率,饿汉的调用效率是非常高的,简单即是高效。
懒汉式
public class Singleton {
private Singleton() {} //私有化构造器
private static Singleton instance = null; //与饿汉相比只设为null,并不new
public static synchronized Singleton getInstance() { //调用实例(注意synchronized)
if (instance == null) { //每次调用判断实例是否为空
instance = new Singleton();
}
return instance;
}
}
第一点,一个对象就是通过私有化构造器实现
第二点是线程安全,这里就有点麻烦了,我们在getInstance方面前面加了一个synchronized,使它同步,试想一下,如果没有这个关键字,如果有10个线程同时在判断之后挂起,等最后一个线程判断完之后全部都创建对象,那这样我们得到的实例顺序是不是就被打乱了,结果不唯一,线程就不安全了。
第三点是延迟加载,通过一个判断来实现,举例子就是,还是自助餐,你新的菜品出来之后,他会先看看自己盘子里还有没有吃的,如果有他就不会来拿了。所以叫懒汉
第四点,因为同步锁的关系,每次执行getInstance都会执行同步检测,这对程序是灾难级的,所以懒加载是5种单例中效率最差的一种。
如果想要兼备高效和延迟呢?如何实现
-
双重检测所实现
-
静态内部类实现
-
枚举实现
1.首先是双重检测所实现,https://www.cnblogs.com/xz816111/p/8470048.html
大家可以看看这位大神的,基本讲的比较详细,双重锁检测的问题也分析也比较到位,我就不献丑了
2.静态内部类实现
public class Singleton {
private Singleton() {} //私有化构造器
private static class SingletonInstence { //用静态内部类来创建实例
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance() { //调用实例
return SingletonInstence.instance;
}
}
第一点我就不赘述了
第二点,首先和饿汉十分像,只是把创建单例工作放入静态内部类当中,所以它自然也是线程安全,理由也是和饿汉式一样。
第三点,延迟加载,为什么多了一个静态内部类就能实现懒加载呢。因为创建实例的动作是在内部类中执行的,只要你动用了getInstence时才会创建实例,就是这样实现了延迟加载。
第四点效率,这几乎是最好的单例模式,因为没有同步的关系,所以效率也十分客观,推荐使用
3.枚举实现
public enum Singleton {
INSTENCE;
}
好了,没有了,就这一句话,是不是都震惊到了
枚举元素本身就是一个单例
唯一遗憾的就是没用延迟加载功能,但是效率是十分高效的
效率总结
饿汉式 > 静态内部实现 > 枚举实现 > 双重检测锁 > 懒汉式