单例模式
来源:互联网 发布:淘宝不开发票怎么办 编辑:程序博客网 时间:2024/05/20 18:41
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式最主要的特点:
- 构造函数不对外开放,一般为private;
- 通过一个静态方法或者枚举返回单例类对象;
- 确保单例类的对象有且只有一个,尤其是在多线程的环境下;
- 确保单例类对象在反序列化时不会重新构建对象。
通过将单例类构造函数私有化,使得客户端不能通过 new 的形式手动构造单例类的对象。单例类会暴露一个共有静态方法,客户端需要条用这个静态方法获取到单例类的唯一对象,在获取到这个单例对象的过程中需要确保线程安全,即在多线程环境下构造单例类的对象也是有且只有一个,这是单例模式较关键的一个地方。
示例代码
- 懒汉式,线程不安全
延迟初始化,一般很多人称为懒汉法,写法一目了然,在需要使用的时候去调用getInstance()函数去获取Singleton的唯一静态对象,如果为空,就会去做一个额外的初始化操作。
public class Singleton { private static Singleton instance = null; private Singleton(){} public static Singleton getInstance() { if(instance == null) instance = new Singleton(); return instance; }}
- 懒汉式,线程安全
需要做到线程安全,就需要确保任意时刻只能有且仅有一个线程能够执行new Singleton对象的操作,所以可以在getInstance()函数上加上 synchronized 关键字,类似于:
public static synchronized Singleton getInstance() { if(singleton == null) instance = new Singleton(); return instance; }
对于绝大部分不需要同步的情况来说,synchronized 会让函数执行效率糟糕一百倍以上,所以就有了double-checked(双重检测)的方法:
public class Singleton { private volatile static Singleton instance = null; private Singleton(){} public static Singleton getInstance() { if (instance == null){ synchronized (Singleton.class){ if (instance == null){ instance = new Singleton(); } } } return instance; }}
当volatile用于一个作用域时,Java保证如下:
(适用于Java所有版本)读和写一个volatile变量有全局的排序。也就是说每个线程访问一个volatile作用域时会在继续执行之前读取它的当前值,而不是(可能)使用一个缓存的值。(但是并不保证经常读写volatile作用域时读和写的相对顺序,也就是说通常这并不是有用的线程构建)。
(适用于Java5及其之后的版本)volatile的读和写建立了一个happens-before关系,类似于申请和释放一个互斥锁[8]
我们假设两个线程A,B同时执行到了getInstance()这个方法,第一个if判断,两个线程同时为true,进入if语句,里面有个 synchronized 同步,所以之后有且仅有一个线程A会执行到 synchronized 语句内部,接着再次判断instance是否为空,为空就去new Singleton对象并且赋值给instance,A线程退出 synchronized 语句,交出同步锁,B线程进入 synchronized 语句内部,if判断instance是否为空,防止创建不同的instance对象,这也是第二个if判断的作用,B线程发现不为空,所以直接退出,所以最终A和B线程可以获取到同一个Singleton对象,之后的线程调用getInstance()函数,都会因为Instance不为空而直接返回,不会受到 synchronized 的性能影响。
- 饿汉式,线程安全
“饿汉法”就是在使用该变量之前就将该变量进行初始化,这当然也就是线程安全的了
public class Singleton {private static Singleton instance = new Singleton();private Singleton(){}public static Singleton getInstance(){ return instance;}}
在该类进行加载的时候就会初始化该对象,而不管是否需要该对象。这么写的好处是编写简单,而且是线程安全的
- 单例、单例模式
- 单例模式-多线程单例模式
- 单件模式(单例模式)
- 设计模式------单例模式
- 设计模式------单例模式
- 设计模式-单例模式
- 设计模式 - 单例模式
- 设计模式---单例模式
- 设计模式---单例模式
- PHP模式-单例模式
- 【设计模式】单例模式
- 设计模式-单例模式
- 设计模式----单例模式
- 设计模式--单例模式
- 设计模式-单例模式
- 单例模式(单子模式)
- 设计模式-单例模式
- [设计模式] 单例模式
- 使用JavaScript实现数组去重的几种方式
- Python pencv documentation文档教程
- 单例模式的个人理解
- python 远程调度进程服务与客户端
- 数据标准化方法
- 单例模式
- Apache+PHP开发环境的配置
- Android 服务类Service 的详细学习
- 实验室项目日志
- RHEL5/6 加载 DVD yum源
- 序列化之-----transient
- mongodb 限制ip访问
- 【算法逻辑】保持字符串内符号位置不变,其他字符随机变化
- 使用Apache POI读取Excel文件,将读取的数据转换成json写入文本文件