当前位置: 首页 > news >正文

介绍单例模式

描述

保证一个类只有一个实例,并且提供一个全局访问点

场景:

重量级的对象,不需要多个实例,如线程池,数据库连接池

实现

1. 懒汉模式
  • 延迟加载的方式 只有在真正使用的时候,才开始实例化
  • 线程安全问题
  • double check 加锁优化
  • 编译器(JIT) cpu有可能对指令进行重排序,导致使用到尚未初始化的实例,可以通过添加volatile关键字,对于volatile修饰的字段,可以防止指令重排
class LazySingleton{private volatile static LazySingleton instance;private LazySingleton(){}public static LazySingleton getInstance(){if (instance == null) {synchronized (LazySingleton.class) {if (instance == null) {instance = new LazySingleton();// 1.分配空间 2.初始化 3.引用赋值}}}return instance;}
}

备注:
javap -v XXX.class可以看class文件的字节码

2. 饿汉模式
  • 类加载的初始化阶段就完成了实例的初始化,本质上是基于JVM类加载机制,保证实例的唯一性
  • 类加载的过程:
    • 加载二进制数据到内存中,生成对应的class数据结构
    • 连接:验证、准备(给类的静态成员变量赋默认值)、解析
    • 初始化:给类的静态变量赋值
      注意:
    • 只有在真正使用对应的类时,才会触发初始化
class HungrySingleton{private static final long serialVersionUID = 4416608876659526091L;private static HungrySingleton instance = new HungrySingleton();private HungrySingleton(){}public static HungrySingleton getInstance(){return instance;}
}
3. 静态内部类
  • 本质上是利用类的加载机制保证线程安全
  • 只有在实际使用的时候,才会触发类的初始化,所以也是懒加载的一种形式
class InnerClassSingleton{private static class InnerClassHolder{private static InnerClassSingleton instance = new InnerClassSingleton();}private InnerClassSingleton(){}public static InnerClassSingleton getInstance(){return InnerClassHolder.instance;}
}
4. 反射攻击实例
public class HungrySingletonTest {public static void main(String[] args) throws Exception {HungrySingleton instance = HungrySingleton.getInstance();HungrySingleton instance1 = HungrySingleton.getInstance();System.out.println(instance);System.out.println(instance1);//        // 反射获取实例Constructor<HungrySingleton> declaredConstructor = HungrySingleton.class.getDeclaredConstructor();declaredConstructor.setAccessible(true);HungrySingleton instance2 = declaredConstructor.newInstance();System.out.println(instance2);  } 
}class HungrySingleton{ private static HungrySingleton instance = new HungrySingleton();private HungrySingleton(){if (instance != null) {throw new RuntimeException("单例不允许创建多个实例!");}}public static HungrySingleton getInstance(){return instance;} 
}
5. 枚举

枚举类型支持反序列化的操作 并且不能用反射攻击
其他类型支持反序列化操作案例

public class HungrySingletonTest {public static void main(String[] args) throws Exception {HungrySingleton instance = HungrySingleton.getInstance();HungrySingleton instance1 = HungrySingleton.getInstance();System.out.println(instance);System.out.println(instance1);//        // 反射获取实例
//        Constructor<HungrySingleton> declaredConstructor = HungrySingleton.class.getDeclaredConstructor();
//        declaredConstructor.setAccessible(true);
//        HungrySingleton instance2 = declaredConstructor.newInstance();
//        System.out.println(instance2);// 序列化HungrySingleton instance2 = HungrySingleton.getInstance();
//        ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("testSerializable"));
//        oss.writeObject(instance2);
//        oss.close();ObjectInputStream ois = new ObjectInputStream(new FileInputStream("testSerializable"));HungrySingleton o = (HungrySingleton) ois.readObject();ois.close();System.out.println(o == instance2);}}class HungrySingleton implements Serializable{private static final long serialVersionUID = 4416608876659526091L;private static HungrySingleton instance = new HungrySingleton();private HungrySingleton(){if (instance != null) {throw new RuntimeException("单例不允许创建多个实例!");}}public static HungrySingleton getInstance(){return instance;}public Object readResolve() throws ObjectStreamException {return getInstance();}
}
http://www.lryc.cn/news/368766.html

相关文章:

  • 【C++修行之道】类和对象(五)日期类的实现、const成员、取地址及const和取地址操作符重载
  • 来腾讯第4天,我已经焦虑昏了啊!
  • MacOS升级ruby版本
  • 【MySQL数据库基础】
  • QT系列教程(9) 主窗口学习
  • 【C++进阶】深入STL之 栈与队列:数据结构探索之旅
  • SpringBoot发邮件服务如何配置?怎么使用?
  • AutoCAD Mechanical机械版专业的计算机辅助设计软件安装包下载安装!
  • json.load报错AttributeError: ‘str‘ object has no attribute ‘load‘
  • 单词记忆(第二周)
  • RAG:如何从0到1搭建一个RAG应用
  • leetcode:67二进制求和
  • 大模型日报2024-06-10
  • 【博士每天一篇文献-综述】Modularity in Deep Learning A Survey
  • Sentinel不使用控制台基于注解限流,热点参数限流
  • HTML做成一个端午节炫酷页面
  • 解决Ubuntu系统/usr/lib/xorg/Xorg占用显卡内存问题原创
  • 【Activiti7系列】基于Spring Security的Activiti7工作流管理系统简介及实现(附源码)(下篇)
  • 解密Spring Boot:深入理解条件装配与条件注解
  • 【数据结构与算法】使用数组实现栈:原理、步骤与应用
  • cell的复用机制和自定义cell
  • Redis 双写一致原理篇
  • 《软件定义安全》之四:什么是软件定义安全
  • 将AIRNet集成到yolov8中,实现端到端训练与推理
  • hcache缓存查看工具
  • Java 数据类型 -- Java 语言的 8 种基本数据类型、字符串与数组
  • kafka-生产者事务-数据传递语义事务介绍事务消息发送(SpringBoot整合Kafka)
  • 免费!GPT-4o发布,实时语音视频丝滑交互
  • DevOps的原理及应用详解(四)
  • 关于选择,关于处事