大号在练葵花宝典 发表于 2025-1-26 00:19:02

玩转单例模式

Java中单例(Singleton)模式是一种广泛利用的设计模式。单例模式的重要作用是保证在Java程序中,某个类只有一个实例存在。一些管理器和控制器常被设计成单例模式。单例模式的好处:

[*]能够制止实例对象的重复创建,不光可以淘汰每次创建对象的时间开销,还可以节约内存空间;
[*]能够制止由于操作多个实例导致的逻辑错误。
单例模式常见模式

饿汉模式

https://img2024.cnblogs.com/blog/1454713/202501/1454713-20250126003914108-892609178.png
 
1.当类被加载时,静态变量会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例将被创建。因为类的加载过程天生是线程安全的,则此过程中创建的静态对象也是线程安全的。利用饿汉式单例,不会出现创建多个单例对象的情况,可确保单例对象的唯一性。2. 类加载过程中,静态变量初始化过程中会将类的成员变量都创建,浪费空间。3.如图例子,main方法中多线程利用getInstance方法拿到的静态对象,全都是同一个,符合单例要求。 懒汉模式

懒汉模式的单例,单线程安全版:https://img2024.cnblogs.com/blog/1454713/202501/1454713-20250126003721662-1458301016.png
但此写法多线程下存在标题:会多次调用构造函数 并未按照懒汉式单例的设计发现有类的静态对象就直接返回此对象,而是多次调用了构造方法创建类的静态对象。原因是多线程调用getInstance方法时,有的线程判断空之后,已经进入了if大括号中,然后时间片被抢,别的线程判断也是空,创建完之后之前的线程拿到cpu直接创建了,导致多次调用构造函数创建。解决前面饿汉式单例的标题:添加Synchronized关键字https://img2024.cnblogs.com/blog/1454713/202501/1454713-20250126003558008-627512655.png
 此方法标题是多个线程试图调用getInstance方法进行判断时都要进行锁定,太低落服从了。缩小加锁范围
https://img2024.cnblogs.com/blog/1454713/202501/1454713-20250126004129469-634605584.png
实际验证在if内加锁的结果和理论一样 多线程照旧会创建多个对象,synchronized关键字放在if里面没有办法解决标题。DCL懒汉式单例(双重检验Double-Checking-Locking)

双重检验的懒汉式单例,注意给静态对象增加volatile关键字,因为构造函数中的new操作不是原子性操作。https://img2024.cnblogs.com/blog/1454713/202501/1454713-20250126004647266-1329205580.png
静态内部类

焦点:就是将前面类的静态变量的生成过程,即new静态常量的过程放入了静态内部类中,由于静态内部类是在利用时才加载,就有了懒加载的结果,做到了懒汉式单例的结果,但又不存在加锁的标题。https://img2024.cnblogs.com/blog/1454713/202501/1454713-20250126004809341-1454234047.png
单例饿汉、懒汉、内部静态类方法总结:


[*]三种方式都是包罗三个部分:public的getInstance方法(给外部提供类的单例对象) 类的静态对象获取 private的类构造器(确保单例)
[*]都是从getInstance获取单例对象,饿汉是直接返回类的静态常量对象,懒汉是要用双重检验锁 然后返回类的静态常量,静态内部类是直接返回类的静态常量对象
[*]静态常量的生成 饿汉式直接final static 修饰一个对象获取new类对象 懒汉式是private static volatile声明了一下 然后在getInstance方法中new了 最后返回new的对象 放入方法中实现了延迟加载 静态内部类是搞了一个内部类,把懒汉的那一句声明和实例化都放到静态内部类中了 用静态内部类实现延迟加载
[*]私有化构造器保证单例,都是在new对象的时候利用到。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 玩转单例模式