创建单例模式(Singleton)的几种方式
来源:互联网 发布:mac dock栏顺序 编辑:程序博客网 时间:2024/05/21 15:04
单例模式可能是最常用到的设计模式了,但是想要正确的使用单例模式却并不简单。
我们先从最简单最常用的方式开始:
懒汉式
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }}
要点:
私有的静态内部引用实例
私有构造函数
共有静态的getInstance()方法,当静态内部引用为空时才实例化
缺点:
多线程环境下不安全
饿汉式
考虑到多线程的条件,还有另外一种常用的简单实现方式:
public class Singleton{ private final static Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; }}
要点:
private, final 和 static 的实例变量
私有化构造函数
共有静态的getInstance()方法
static 的实例变量在类加载到内存的时候就会初始化,创建实例是线程安全的
缺点:
实例在类初始化一开始就被创建了,哪怕后来根本没有使用它
如果实例的创建时依赖于外部的参数/文件的话,这种方式就不适用了
双重检验锁
为了避免上面饿汉式的缺点,我们来考虑改进懒汉式单例模式来支持多线程的情况。最直接的想法就是对 getInstance()
加锁,但是这样一来同一时间只能有一个线程调用单例实例,效率低下。通过分析,我们可以发现其实不用对整个 getInstance()方法加锁,只需要在实例为空需要创建时加锁。
public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance;}
要点:
两次检查
instance == null
,一次是在同步块外,一次是在同步块内
使用两次判断的原因:有可能多个线程同时进入第一个
if
判断,如果在同步块中不再次判断的话,有可能生成多个实例
缺点:
由于JVM指令重排序的优化,在
instance = new Singleton();
仍有可能生成多个实例
在JVM指令优化时,
instance = new Singleton();
并不是一个原子操作,而是3个步骤:
1. 为instance分配内存
2. 调用 Singleton构造函数初始化成员变量
3. 将instance对象指向分配的内存空间 (instance非null)
在JVM编译优化时,上面3个步骤并不是顺序执行的,有可能重新排列执行的顺序,有可能是 1-2-3, 或者 1-3-2。如果是 1-3-2的执行顺序的话,有可能出现这种情况:线程1执行完了1-3步骤后退出了同步块,这个时候instance已经是非null了,但还没被初始化,这个时候线程2进入同步块,判断instance为非null,所有直接返回没有初始化的对象,在后面的使用中自然会报错。
静态内部类
public class Singleton{ private static class SingletonHolder{ private static final Singleton INSTANE = new Singleton(); } private Singleton(){} public static final Singleton getInstance(){ return SingletonHolder.INSTANCE; }}
优点:
- 使用JVM本身机制保证了线程安全问题;
- SingletonHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;
- 读取实例的时候不会进行同步,没有性能缺陷;
- 不依赖 JDK 版本
- 创建单例模式(Singleton)的几种方式
- 单例模式singleton的几种实现方式
- Singleton单例模式的几种创建方法
- Singleton Pattern (单例or单件模式)的几种实现方式
- 【Android进阶】设计模式------Singleton单例的几种实现方式
- 创建单例模式的几种方式
- 浅谈单例模式的几种创建方式
- 单例模式--Singleton模式的几种解法分析
- 单例模式(singleton pattern)的几种实现
- Singleton单例模式 几种实现的优劣
- java实现单例singleton的几种模式
- 单例模式(Singleton)的创建
- 单例模式(Singleton)的创建
- Singleton模式的几种实现方式
- singleton模式的几种实现方式
- 单例的几种创建方式
- 创建单例的几种方式
- 单例模式的三种实现方式:singleton
- 今天工作中遇到的两个问题。
- 手机屏幕横竖屏切换,activity生命周期发生改变
- 在 ML2 中配置 Vlan Network- 每天5分钟玩转 OpenStack(93)
- 如何提升深度学习的性能?
- 6 进度条
- 创建单例模式(Singleton)的几种方式
- 浅析 Linux fasync 异步通知
- 7 表格元素
- 创建存储过程
- 对二叉树和平衡树测试
- 基础商务谈判培训技巧
- html5地理信息demo
- Oracle 查看表空间的大小及使用情况sql语句
- 基于状态机的按键扫描的实现