设计模式之———单例模式的问题及效率比较
来源:互联网 发布:centos owncloud 安装 编辑:程序博客网 时间:2024/05/17 22:54
1. 出现问题(枚举式单例除外)
-使用反射生成多个单例对象
- 使用序列化反序列化生成多个单例对象
2. 问题展示及解决方法(以饿汉式为例)
2.1 反射实现
public class SingletonDemo6 { // 类初始化时,立即加载这个对象(没有延迟加载的优势),加载类时,天然的线程安全 private static SingletonDemo6 instance = new SingletonDemo1(); // 私有构造器 private SingletonDemo6() {} // 方法不用同步,调用效率高 public static SingletonDemo6 getInstance() { return instance; }}// 饿汉式测试反射问题类public class Test { public static void main(String[] args) { // 正常测试 System.out.println(SingletonDemo6.getInstance()); System.out.println(SingletonDemo6.getInstance()); // 反射测试 Class<SingletonDemo6> clazz = (Class<SingletonDemo6>) Class.forName("com.design.singleton.SingletonDemo6"); Constructor<SingletonDemo6> con = clazz.getDeclaredConstructor(null); con.setAccessible(true); // 设置构造函数的访问权限,必须有 System.out.println(con.newInstance()); System.out.println(con.newInstance()); }}
测试结果: com.design.singleton.SingletonDemo6@311e170c com.design.singleton.SingletonDemo6@311e170c com.design.singleton.SingletonDemo6@2e7b2e05 com.design.singleton.SingletonDemo6@190a621a
2.2 反射的解决方法
在调用构造方法时,先判断实例是否存在,如果已存在则不允许再创建新的对象
public class SingletonDemo6 { ... // 修改私有构造器 private SingletonDemo6() { if(instance != null) { throw new RuntimeException(); } } ...}
2.3 反序列化实现
public class SingletonDemo6 implements Serializable { ...}// 反序列化测试public class Test { public static void main(String[] args) { // 正常测试 SingletonDemo6 s1 = SingletonDemo6.getInstance(); SingletonDemo6 s2 = SingletonDemo6.getInstance(); System.out.println(s1); System.out.println(s2); // 反序列化测试 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\a.txt")); oos.writeObject(); oos.close(); ObjectInputeStream ois = new ObjectInputStream(new FileInputStream("D:\\a.txt")); SingletonDemo6 s3 = (SingletonDemo6) ois.readObject(); ois.close(); System.out.println(s3); }}
结果: com.design.singleton.SingletonDemo6@6c0267a com.design.singleton.SingletonDemo6@6c0267a com.design.singleton.SingletonDemo6@2fdb3aac
2.4 反序列化的解决方法
添加一个Object类型的回调方法readResolve()
public class SingletonDemo6 implements Serializable { ... // 在反序列化时,直接调用返回对象,而不是返回新的对象 private Object readResolve() { return instance; } ...}
结果: com.design.singleton.SingletonDemo6@6c0267a com.design.singleton.SingletonDemo6@6c0267a com.design.singleton.SingletonDemo6@6c0267a
3. 不同单例模式的效率比较
3.1 五种单例模式在多线程下的效率比较
CountDownLatch:同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一只等待。
- - countDown():当前线程调用此方法,则计数器减一。
- - await():调用此方法会一直阻塞当前线程,直到计数器的值为0。
import java.util.concurrent.CountDownLatch;public class Test3 { public static void main(String[] args) throws Exception { int threadCount = 100; // 开启线程个数 final int n = 1000000; // 每个线程执行次数 final CountDownLatch count = new CountDownLatch(threadCount); long start = System.currentTimeMillis(); for (int i = 0; i < threadCount; i++) { new Thread(new Runnable() { @Override public void run() { for (int j = 0; j < n; j++) { Object o1 = SingletonDemo1.getInstance();// Object o2 = SingletonDemo2.getInstance();// Object o3 = SingletonDemo3.getInstance();// Object o4 = SingletonDemo4.getInstance();// Object o5 = SingletonDemo5.INSTANCE; } count.countDown(); } }).start(); } count.await(); long end = System.currentTimeMillis(); System.out.println("耗时:" + (end - start)); }}
3.2 比较结果(供参考)
0 0
- 设计模式之———单例模式的问题及效率比较
- 设计模式之—单例模式
- 设计模式之—单例模式
- 设计模式之—单例模式
- 设计模式之—单例模式
- 设计模式之—单例模式
- 设计模式之单例模式——应用最广泛的设计模式
- GOF23设计模式之——单例设计模式
- 设计模式之——单例设计模式
- 设计模式笔记之——单例设计模式
- 设计模式之单例模式 (五种单例模式实现方式) 并利用CountDownLatch类在多线程下比较效率
- 设计模式GOF23之单例模式效率测试与反射和反序列化问题的解决
- 设计模式之——单例
- 设计模式—单例设计模式
- java设计模式之五 —— 单例模式的三种模式优缺点整理
- php设计模式之———单例模式
- 设计模式之——单例模式
- 探索设计模式之六——单例模式
- 一些不常见的Go命令参数详解
- bootstrap-datepicker 插件修改为默认中文
- Android硬件抽象层(HAL)概要介绍
- 顺序表应用8:最大子段和之动态规划法
- Ubuntu16.04下编译Android 6.0 源码
- 设计模式之———单例模式的问题及效率比较
- Ubuntu 用vsftpd 配置FTP服务器
- 自定义百度网盘分享密码 提取码
- SQL Server的Merge —— 一步实现 insert,update,delete
- Lambda表达式使用汇总
- AVL树
- Hadoop分布式环境搭建
- 【Linux 系统编程】shell 命令和流程控制(二)
- Java RMI 框架(远程方法调用)