【读书】二、单例模式
2016-02-19 23:34
309 查看
特点:
1.构造函数不外放,一般都是private
2.通过暴露一个public的静态方法或者枚举来返回一个单例对象
3.在多线程环境下面,确保单例类对象有且只有一个
4.确保单例类对象再反序列化时候不会重新构建对象
懒汉模式:
优点:需要时候才实例化,节约资源
缺点:每次调用getInstance()都要同步,造成不必要的同步开销
Double checkLock实现单例:
注意DCL是有问题的:
这句并不是原子操作,它可以拆分三件事:
(1).给Singleton的实例分配内存
(2).调用Singleton的构造函数,创建对象
(3).将singleton的对象指向内存分配的空间
但是,由于Java编译器允许处理器乱序执行,以及JDK1.5之前JVM中Cache,寄存器以及主内存回写顺序的规定,(2)与(3)的顺序不是固定的,
所以可能执行顺序是123,也可能是132
如果是132,那么此时比如A线程执行到13,还未执行2,此时B线程也在执行,检查singleton非空,直接使用,就会出错
所如果是JDK1.5以及之后的版本,加上Volatile关键字:
这样就可以保证singleton对象每次都是从主内存中读取。
静态内部类单例模式:
优点:只有第一次调用getInstance才会导致sInstance被初始化,第一次调用时候会导致虚拟机加载SingletonHolder类,
这样能保证线程安全,也能保证单例对象唯一,还能延迟单例实例化
枚举单例:
优点:线程安全,唯一,还能防止反序列化。
破坏单例对象的唯一:
1.反射
2.序列化与反序列化(原因:序列化会通过反射调用无参数的构造方法创建一个新的对象。)
http://www.hollischuang.com/archives/1144
如何防止被序列化?添加一个ReadResolve方法。
1.构造函数不外放,一般都是private
2.通过暴露一个public的静态方法或者枚举来返回一个单例对象
3.在多线程环境下面,确保单例类对象有且只有一个
4.确保单例类对象再反序列化时候不会重新构建对象
懒汉模式:
public class Singleton{ private static Singleton instance; //1.构造函数不对外开放 private Singleton{ } //2.通过一个静态方法来返回单例类对象 //3.加了synchronized,在多线程访问的时候,同一时刻只能有一个线程能够用synchronized修饰的方法或者代码块。 //也就是getInstance是一个同步方法,保证多线程下对象唯一 public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
优点:需要时候才实例化,节约资源
缺点:每次调用getInstance()都要同步,造成不必要的同步开销
Double checkLock实现单例:
public class Singleton{ private volatile static Singleton singleton; private Singleton (){} public static Singleton getInstance() { //第一层判空是为了避免不必要的同步 //从而只有第一次的时候才会加锁,之后就不会加锁 if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { //第二层判空是为了在null的情况下创建实例 singleton = new Singleton(); } } } return singleton; } }
注意DCL是有问题的:
singleton = new Singleton();
这句并不是原子操作,它可以拆分三件事:
(1).给Singleton的实例分配内存
(2).调用Singleton的构造函数,创建对象
(3).将singleton的对象指向内存分配的空间
但是,由于Java编译器允许处理器乱序执行,以及JDK1.5之前JVM中Cache,寄存器以及主内存回写顺序的规定,(2)与(3)的顺序不是固定的,
所以可能执行顺序是123,也可能是132
如果是132,那么此时比如A线程执行到13,还未执行2,此时B线程也在执行,检查singleton非空,直接使用,就会出错
所如果是JDK1.5以及之后的版本,加上Volatile关键字:
private volatile static Singleton singleton;
这样就可以保证singleton对象每次都是从主内存中读取。
静态内部类单例模式:
public class Singleton{ private Singleton{} public static Singleton getInstance(){ return SingletonHolder.sInstance; } /* 静态内部类 */ private static class SingletonHolder{ private static final Singleton sInstance = new Singleton(); } }
优点:只有第一次调用getInstance才会导致sInstance被初始化,第一次调用时候会导致虚拟机加载SingletonHolder类,
这样能保证线程安全,也能保证单例对象唯一,还能延迟单例实例化
枚举单例:
public enum SingletonEnum{ INSTANCE; }
优点:线程安全,唯一,还能防止反序列化。
破坏单例对象的唯一:
1.反射
2.序列化与反序列化(原因:序列化会通过反射调用无参数的构造方法创建一个新的对象。)
http://www.hollischuang.com/archives/1144
如何防止被序列化?添加一个ReadResolve方法。
public class Singleton implements Serializable{ private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } private Object readResolve() { return singleton; } }
相关文章推荐
- 装修之卫生间的处理
- 简单的UIPickView功能
- 第38课:BlockManager架构原理、运行流程图和源码解密
- 第三百二十三天 how can I 坚持
- 移动开单软件 手持PDA开单扫描打印系统开发介绍
- 2016第7周五
- send断点数据地址
- 强制删除右键菜单
- android自定义控件波纹ripple效果
- 2016/2/19 css样式表 Cascading Style Sheet 叠层样式表 美化HTML网页
- Android Studio 学习笔记01
- 基于opencv的形态学滤波
- 4Sum
- SAX和DOM解析XML区别
- HDU2084 数塔 【DP问题】
- leetcode 19: Remove Nth Node From End of List
- Synchronized block 为String 时的情况
- 重新定义团队 谷歌的自由精神对所有公司都适用
- UVa 227 - Puzzle
- 数据结构基础之串