一、定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
二、结构和说明
三、基本实现
四、认识单例模式
1、单例模式的功能
单例模式的功能是用来保证这个类的运行期间只会被创建一个类实例,并提供一个全局唯一访问这个类实例的访问点。
2、单例模式的范围
是一个ClassLoader及其子ClassLoader的范围
3、单例模式的命名
一般建议单例模式的方法命名为:getInstance()。
单例模式的名称:单例、单件、单体等等,翻译的不同,都是指的同一个模式。
五、单例模式过程
这里以懒汉式为例:(懒汉式:线程不安全,饿汉式:线程安全)
private Singleton(){}
2、定义一个方法来为客户端提供类实例。3、这个方法需要定义成类方法,也就是要加static
public static Singleton getInstance(){
//6、判断存储实例的变量是否有值
if(instance == null){
//6.1、如果没有,就创建一个类实例,并把值赋值给存储类实例的变量
instance = new Singleton;
}
//6.2、返回instance。
return instance;
}
4、定义一个变量来存储创建好的类实例。
5、因为这个变量要在静态方法中修饰,所以需要加上static修饰
private Singlenton instance = null;
六、单例模式调用时序图
七、延迟加载思想
什么是延迟加载呢?
通俗点说,就是一开始不要加载资源或者数据,一直等到马上就要使用这个资源或者数据了,躲不过去了才加载,所以也称Lazy Load,不是懒惰,是“延迟加载”,这在实际开发中是一种很常见的思想,尽可能的节约资源。(懒汉式)
八、缓存的思想
单例模式的懒汉式实现还体现了缓存的思想,缓存也是实际开发中非常常见的功能。
简单讲就是,如果某些资源或者数据会被频繁的使用,可以把这些数据缓存到内存里面。每次操作的时候,先到内存里面找,看有没有这些数据,如果有,那么就直接使用,如果没有那么就获取它,并设置到缓存中,下一次访问的时候可以直接从内存中获取了。从而节省大量的时间,当然,缓存是一种典型的空间换时间的方案。
九、单例模式优缺点
(2)饿汉式是线程安全的,因为虚拟机保证了只会装载一次。
(3)如何实现懒汉式的线程安全呢?加载synchronized即可
(4)双重检查加锁
所谓双重检查加锁机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。
双重检查加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。
注意:在Java1.4及以前版本中,很多JVM对于volatile关键字的实现有问题,会导致双重检查加锁的失败,因此本机制只能用在Java5及以上的版本。
十、在java中二种更好的单例实现方式
1、Lazy initialization holder class 模式,这个模式综合使用了java的类级内部类和多线程缺省同步锁的知识,很巧妙的同时实现了延迟加载和线程安全。
2、单例和枚举:按照《高效java第二版》中的说法:单元素的枚举类型已经成为实现Singleton的最佳方法。
十一、单例模式的本质:控制实例数目
十二、何时选用单例模式
当需要控制一个类的实例只能有一个,而且客户只能从一个全局访问点访问它时,可以选用单例模式,这些功能恰好是单例模式要解决的问题。