单例模式
来源:互联网 发布:淘宝怎么好友代付 编辑:程序博客网 时间:2024/05/01 09:19
本篇博客主要记录一下单例模式。
单例模式大家应该都不陌生,主要用于创建一个“独一无二”的对象。
它基本的写法类似于:
public class Singleton { private static Singleton uniqueInstance; private Singleton() {} public static Singleton getInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; }}
容易看出,单例模式其实就是利用一个静态变量uniqueInstance来记录Singleton的唯一实例。
Singleton的构造器被声明为私有的,因此只有内部方法可以调用。
当客户端代码试图获取单例对象时,必须调用其静态方法getInstance。
在getInstance方法中,将判断Singleton是否被实例化过。
如果实例化过,则直接返回uniqueInstance;否则,将先实例化单例对象。
通过这种方式,外部类不能随意地实例化Singleton;
仅能通过Singleton提供的接口,获取对象。
而Singleton又管制了自身的创建,于是最终保证Singleton“独一无二”。
单例模式的定义和结构图都很简单,如下所示:
单例模式确保一个类只有一个实例,并提供一个全局访问点。
如图所示,单例模式其实就只有一个类,
它主要是通过上文中代码的固定“套路”来保证对象的“独一无二”。
需要注意的是,在多线程的场景下,上述单例的实现方式,将会产生问题。
例如,在初次初始化时,两个线程同时进入到getInstance方法,
并判断uniqueInstance为null,此时将会初始化多个实例。
针对这个问题,在多线程场景下,主要有三种解决方案。
1、同步getInstance方法
按照这种方案修改后的代码类似于:
public class Singleton { private static Singleton uniqueInstance; private Singleton() {} //增加synchronized关键字 //迫使每个线程在进入该方法前,必须等待其它线程离开 public static synchronized Singleton getInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; }}
这种修改方案比较简单,唯一的缺点是对性能有影响。
如果getInstance将被频繁调用,那么就不能这么改。
2、由JVM初始化类时创建单例
按照这种方案修改后的代码类似于:
public class Singleton { //类被加载时,就创建出单例 //保证了线程安全 private static Singleton uniqueInstance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return uniqueInstance; }}
一般单例被频繁使用,或创建和运行的负担不重时,可以采取这种方式。
3、利用“double checked locking”来同步getInstance方法
public class Singleton { //这里注意使用volatile关键字 //保证一个线程创建单例后,另一个线程能够发现这种改变 private volatile static Singleton uniqueInstance; private Singleton() {} public static Singleton getInstance() { if (uniqueInstance == null) { //只有第一次创建时,才会真正利用synchronized进行同步 //因此对性能的影响较小 synchronized (Singleton.class) { //进入同步块后,再次判断是否创建 if (uniqueInstance == null) { uniqueInstance = new Singleton(); } } } return uniqueInstance; }}
这种方式可以看作对第1种方式的性能优化。
最后,需要说明的是:
每个类加载器都定义了一个命名空间,如果有两个以上的类加载器,
不同的类加载器可能会加载同一个类,从整个程序来看,同一个类会被加载多次。
如果这种事情发生在单例上,就会产生多个单例并存的现象。
因此,如果程序中有多个类加载器又使用了单例模式,
那么最后指定同一个类加载器加载单例类。
- 单例、单例模式
- 单例模式-多线程单例模式
- 单件模式(单例模式)
- 设计模式------单例模式
- 设计模式------单例模式
- 设计模式-单例模式
- 设计模式 - 单例模式
- 设计模式---单例模式
- 设计模式---单例模式
- PHP模式-单例模式
- 【设计模式】单例模式
- 设计模式-单例模式
- 设计模式----单例模式
- 设计模式--单例模式
- 设计模式-单例模式
- 单例模式(单子模式)
- 设计模式-单例模式
- [设计模式] 单例模式
- javascript 简单滚动图片
- 可伸缩架构简短系列
- 杭电oj 1175连连看
- 紫书例题6-3 UVa442 (栈
- nginx 常见错误及优化
- 单例模式
- 表达式计算(中缀转后缀,然后求值)
- 《java学习笔记》MD5加密算法
- mysql-按天或者按月统计数据
- SSM框架整合(三)
- ORA-12519: TNS:no appropriate service handler found 解决
- ubuntu下安装lua的时候出现 lua.c:80:31: fatal error: readline/readline.h: 没有那个文件或目录 这样的报错
- [POI2010]TES-Intelligence Test 洛谷3500 二分
- 安卓目录res/menu中showAsAction用法