单例模式
来源:互联网 发布:c语言期末考试试题 编辑:程序博客网 时间:2024/05/23 22:49
设计模式-单例模式
单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。
有时候,我们要求一个类仅有一个实例,这种场景下单例模式就可以派上用场。先看下单例模式的类图。
UML类图
单例模式的关键是构造函数定义为私有的,防止在外部实例化该类对象,并提供一个获取单例对象的公共方法。
代码实现
单例模式实现可分为单线程和多线程的,也即是否线程安全的。
单线程的单例
/** * <p>文件描述: 单线程的单例</p> * * @Author luanmousheng * @Date 17/6/25 下午2:48*/public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }}
多线程的单例
多线程下创建单例不是线程安全的,有两种方式可以解决这个问题,DCL加锁机制和静态初始化机制。加锁保证了同时只有一个线程去创建单例,静态初始化是借助了类加载机制。
双重检查锁定(Double Check Locking, DCL)
/** * <p>文件描述: 双重检查锁定机制:DCL</p> * * @Author luanmousheng * @Date 17/6/25 下午2:59*/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; }}
双重检查锁定的第一次检查,是为了判断实例是否已经存在,只有当实例不存在才会去创建,否则每次调用getInstance方法都要去做同步锁定,效率太低。
在第一次检查和第二次检查之间的同步块,是为了保证同时只有一个线程创建实例对象。
那为何要有第二次检查呢?假如一开始单例实例不存在,A和B线程都通过了第一次检查,假设线程A竞争到了同步锁,进入到了同步块内,直接创建实例。当线程A离开同步块后,线程B拿到同步锁并进入到同步块,也会创建实例,那就创建了两次实例。因此第二次检查是必要的。
静态变量singleton为何被声明为volatile的?singleton = new Singleton()
不是原子的操作,将singleton声明为volatile,禁止了指令重排序,防止其他线程拿到了还未初始化完成的对象引用(CPU可能先给singleton赋值为对象的地址,然后去初始化对象,此时其他线程就可能拿到未初始化完成的对象引用)。
静态初始化机制
静态初始化机制包括类静态变量的初始化和静态块的初始化
静态变量初始化
/** * <p>文件描述: 静态变量初始化</p> * * @Author luanmousheng * @Date 17/6/25 下午3:33*/public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; }}
这种方法利用了类加载机制,类加载的时候就创建了对象。
静态块初始化
/** * <p>文件描述: 静态内部类机制</p> * * @Author luanmousheng * @Date 17/6/25 下午3:40*/public class Singleton { /** * 静态内部类 */ private static class SingletonHolder { private static final Singleton instance = new Singleton(); } /** * <p>功能描述: 只有真正调用该方法时才会去初始化instance</p> * * @Author luanmousheng * @Date 17/6/25 下午3:42 */ public static Singleton getInstance() { return SingletonHolder.instance; }}
这种方式最大的优点是延迟初始化,只有在需要的时候才会去创建实例。
参考:
- 大话设计模式. 程杰著
- 单例、单例模式
- 单例模式-多线程单例模式
- 单件模式(单例模式)
- 设计模式------单例模式
- 设计模式------单例模式
- 设计模式-单例模式
- 设计模式 - 单例模式
- 设计模式---单例模式
- 设计模式---单例模式
- PHP模式-单例模式
- 【设计模式】单例模式
- 设计模式-单例模式
- 设计模式----单例模式
- 设计模式--单例模式
- 设计模式-单例模式
- 单例模式(单子模式)
- 设计模式-单例模式
- [设计模式] 单例模式
- LeetCode(5)
- C-关键字
- static在C和C++中的用法和区别
- IntelliJ IDEA 的配置和使用
- python2 urlencode 中文demo
- 单例模式
- 用WordPress程序做博的一些基本设置让你的博客飞起来
- 【转载】ABAP:Function 之 Read_Text函数的使用方法
- 【Tensorflow】辅助工具篇——matplotlib介绍(下)
- STM32->ADC
- kotlin 基本语法(三)
- 初次使用CPLEX
- 一 Zookeeper简介
- Gank基友系列--简单的纯单例实现