设计模式学习笔记——单例模式
2016-03-27 16:28
330 查看
单例模式
单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。结构图
保证三点:
1.私有的构造方法,防止从类的外部实例化。
2.指向自己实例的私有静态引用。
3.以自己实例为返回值的静态的公有的方法。
饿汉单例
饿汉单例,在单例类加载的时候,实例化一个对象交给引用。代码实现
/** * 饿汉单例:在类加载的时候,实例化一个对象交给自己的引用 * * @author xukai 2016年3月27日 下午2:49:12 * */ public class Singleton { // 加载时实例化 private static Singleton singleton = new Singleton(); /** * 私有的构造方法,除反射和克隆无法重新实例化 */ private Singleton() { } /** * 返回实例对象 */ public static Singleton getInstance() { return singleton; } }
懒汉单例
懒汉单例,调用获取单例的实例方法时,实例化对象。(线程安全)代码实现
/** * 懒汉单例:调用获取实例方法时,实例化对象 * * @author xukai 2016年3月27日 下午2:52:40 * */ public class Singleton { private static Singleton singleton = null; /** * 私有的构造方法,除反射无法重新实例化 */ private Singleton() { } /** * synchronized对方法加锁,同步 */ public static synchronized Singleton getInstance(){ if(singleton == null) // 1 { singleton = new Singleton(); //2 } return singleton; } }在Java多线程中,当第一次调用getInstance方法时,需要同步(synchronized),非第一次调用此方法都需要付出同步代价,太消耗资源,下面有双重检查锁解决此问题。
双重检查锁
/** * 双重检查锁 * * @author xukai 2016年3月27日 下午3:42:00 * */ public class Singleton { private static Singleton singleton = null; /** * 私有的构造方法,除反射无法重新实例化 */ private Singleton() { } public static Singleton getInstance() { if (singleton == null) // 1 { // 对类进行加锁,当前对象只能被一个对象调用或拥有 synchronized (Singleton.class) // 2 { if (singleton == null) // 3 { singleton = new Singleton(); } } } return singleton; } }由于懒汉模式非第一次调用获取实例方法都要付出同步的代价,这种代价太高。而双重检查锁是在判断之后进行有选择的加锁。
双重检查锁:
1.进入getInstance,singleton引用对象为空
2.对类进行加锁,防止此时有多个线程都是访问。
3.再次判断此时singleton是否为空。
4.实例化对象。
这里的第三步是为了防止出现这种情况:线程1和线程2同时进入getInstance方法中,假如线程1先获得了当前对象锁,并执行了下面的操作,实例化对象,将锁释放,此时线程2处于代码中的2位置,继续执行,获得当前类的锁,实际上线程1已经实例化出一个对象了,假如代码中的位置3没有添加空判断,那么会重新实例一个新的对象。
单例模式优点
1.在内存中只有一个对象,节省内存空间。2.避免频繁的创建销毁对象,可以提高性能。
3.避免对共享资源的多重占用。
4.可以全局访问。
使用场景
1.需要频繁实例化然后销毁对象。2.创建对象时过多或者消耗资源过多,经常使用。
3.有状态的工具类对象。
4.频繁访问数据库或文件的对象。
注意
1.不要使用反射,否则会实例化一个新对象。2.不要断开单例类对象和它的静态引用。
3.多线程使用共享资源,注意线程安全。
Java中,优先使用饿汉模式。C++中一般使用懒汉模式。
相关文章推荐
- 选夫婿1
- vector与list区别
- hdu 1712 ACboy needs your help(分组背包入门)
- 常见数据结构之JavaScript实现
- 想写一系列关于css draft的博客
- PHP记录 字符串 函数
- [BZOJ2843]极地旅行社(LCT)
- App架构经验总结
- hadoop源代码分析(二)从wordCount开始,剖析mapreduce的运行机制
- Spring容器中bean的生命周期以及关注spring bean对象的后置处理器:BeanPostProcessor(一个接口)
- 《Linux内核设计与实现》第十八章读书笔记
- PHP连接数据库实现注册页面的增删改查操作
- 1002 田忌赛马问题
- BZOJ 1201: [HNOI2005]数三角形
- 不敢死队问题
- 使用Pip安装distribute、nose、virtualenv
- 常用算法——排序(三)
- Java多线程系列--“JUC集合”09之 LinkedBlockingDeque
- poj3001
- 五子棋AI算法第八篇-重构代码