玩转单例模式
Java中单例(Singleton)模式是一种广泛使用的设计模式。单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在。一些管理器和控制器常被设计成单例模式。
单例模式的好处:
- 能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间;
- 能够避免由于操作多个实例导致的逻辑错误。
单例模式常见模式
饿汉模式
1.当类被加载时,静态变量会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例将被创建。因为类的加载过程天生是线程安全的,则此过程中创建的静态对象也是线程安全的。使用饿汉式单例,不会出现创建多个单例对象的情况,可确保单例对象的唯一性。
2. 类加载过程中,静态变量初始化过程中会将类的成员变量都创建,浪费空间。
3.如图例子,main方法中多线程使用getInstance方法拿到的静态对象,全都是同一个,符合单例要求。
懒汉模式
懒汉模式的单例,单线程安全版:
但此写法多线程下存在问题:会多次调用构造函数 并未按照懒汉式单例的设计发现有类的静态对象就直接返回此对象,而是多次调用了构造方法创建类的静态对象。原因是多线程调用getInstance方法时,有的线程判断空之后,已经进入了if大括号中,然后时间片被抢,别的线程判断也是空,创建完之后之前的线程拿到cpu直接创建了,导致多次调用构造函数创建。
解决前面饿汉式单例的问题:添加Synchronized关键字
此方法问题是多个线程试图调用getInstance方法进行判断时都要进行锁定,太降低效率了。缩小加锁范围
实际验证在if内加锁的结果和理论一样 多线程还是会创建多个对象,synchronized关键字放在if里面没有办法解决问题。
DCL懒汉式单例(双重检验Double-Checking-Locking)
双重检验的懒汉式单例,注意给静态对象增加volatile关键字,因为构造函数中的new操作不是原子性操作。
静态内部类
核心:就是将前面类的静态变量的生成过程,即new静态常量的过程放入了静态内部类中,
由于静态内部类是在使用时才加载,就有了懒加载的效果,做到了懒汉式单例的效果,但又不存在加锁的问题。
单例饿汉、懒汉、内部静态类方法总结:
- 三种方式都是包含三个部分:public的getInstance方法(给外部提供类的单例对象) 类的静态对象获取 private的类构造器(确保单例)
- 都是从getInstance获取单例对象,饿汉是直接返回类的静态常量对象,懒汉是要用双重检验锁 然后返回类的静态常量,静态内部类是直接返回类的静态常量对象
- 静态常量的生成 饿汉式直接final static 修饰一个对象获取new类对象 懒汉式是private static volatile声明了一下 然后在getInstance方法中new了 最后返回new的对象 放入方法中实现了延迟加载 静态内部类是搞了一个内部类,把懒汉的那一句声明和实例化都放到静态内部类中了 用静态内部类实现延迟加载
- 私有化构造器保证单例,都是在new对象的时候使用到。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~