单例模式
来源:互联网 发布:2.0音箱 知乎 编辑:程序博客网 时间:2024/06/07 00:36
总结常见的单例模式
1.单例模式概述
单个例子模式定义应该是这样的:一个类在被使用的时候只能有一个实例化对象,这种模式就称为单例模式。概念不难,实现这个模式有相应的套路,前人已经为我们总结出了经验。大致思路是这样的:为了在使用这个类时不产生多个对象,首先构造方法要私有,第二,构造一个静态方法产生这个单个实例。基于这两点思想,同时考虑多线程情况下使用这个类也只生成一个对象,总结出以下4种写法。
2.单例分类
单例模式的实现有两种类型,饿汉式和懒汉式。
饿汉式:
/** * 单例模式(饿汉式) */class Singleton{ public static final Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; }}
这是最简单的一种单例模式,称为饿汉式,在Singleton类加载时,instance对象就初始化了,而在外部只能通过调用getInstance静态方法得到这个唯一的对象,因为构造方法私有了,无法new一个对象。不管是否调用getInstance方法,在类加载过程中都创建好了实例,同时也避免了多线程下调用getInstanc方法而产生的线程安全问题,缺点是无论是否调用getInstance方法,对象都已创建,这样会占用一定的内存空间。由于这种方法比较粗暴,所以称为饿汉式。
懒汉式
为了保证线程安全,这里介绍三种方式
第一种(常规方式)
/** * 单例模式(懒汉式) */class Singleton{ public static Singleton instance = null; private Singleton(){} public static synchronized Singleton getInstance(){ if (instance == null){ instance = new Singleton(); } return instance; }}
这种方法在类加载时并不会初始化对象,而是在调用getInstance方法时才会初始化对象,getInstance方法使用synchronized关键字修饰可以解决线程安全问题。缺点是每次调用都会进行同步,这样对性能是有影响的。
第二种(双重校验方式)
/** * 单例模式(双重校验模式) */class Singleton{ public static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){ if (instance == null){ synchronized (Singleton.class){ if (instance == null){ instance = new Singleton(); } } } return instance; }}
相较于常规方式,这种方式只在第一次实例化对象的时候需要同步,之后就不需要,这样节省性能,由于同步机制,所以要进行两次判断,所以叫双重验证方式
第三种(静态内部类方式)
/** * 单例模式(静态内部类方式) */class Singleton { private Singleton() {} public static class SingletonHoder { public static final Singleton instance = new Singleton(); } public static Singleton getInstance(){ return SingletonHoder.instance; }}
这是一种非常巧妙的方式,利用了静态内部类实现。这种方式利用了classloder的机制来保证初始化instance时只有一个线程,而不是只要Singleton类被装载了instance就会被实例化(没有达到lazy loading效果),Singleton类被装载了,instance不一定被初始化,因为SingletonHolder类没有被主动使用,只有显式通过调用getInstance方法时,才会显式装载SingletonHolder类,从而实例化instance。在某些情况下,如果实例化instance很消耗资源,我想让他延迟加载,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这种方式也没有使用同步,但保证了线程安全,所以相比前两种要更就显得合理一些。
3.总结
还有一种更好的方式,是《Effective Java》推荐的,就是枚举方式,这个以后再做总结。
- 单例、单例模式
- 单例模式-多线程单例模式
- 单件模式(单例模式)
- 设计模式------单例模式
- 设计模式------单例模式
- 设计模式-单例模式
- 设计模式 - 单例模式
- 设计模式---单例模式
- 设计模式---单例模式
- PHP模式-单例模式
- 【设计模式】单例模式
- 设计模式-单例模式
- 设计模式----单例模式
- 设计模式--单例模式
- 设计模式-单例模式
- 单例模式(单子模式)
- 设计模式-单例模式
- [设计模式] 单例模式
- PL通过EMIO方式外接PHY芯片的实验
- 洛谷 [P1280] 尼克的任务
- 笔记24 | 一个中间打开界面的动画
- cocos2d-js 自动绑定代码
- Spark性能优化之shuffle调优
- 单例模式
- 解决mavenweb项目ClassNotFound:DispacherServlet not found
- 【scala 笔记(9)】 隐式转换 和 隐式参数-- implicit
- tensorflow不同版本安装与升级/降级
- 10-20-pm-C++开发面试题
- PHP类和对象之重载
- Linux下MySQL备份以及crontab定时备份(crontab表达式简介)
- HEVC标准中的图像分割(1),slice,tile,CTU,CU,PU,TU等
- [bzoj2456][数论]mode