玩转单例模式

Java中单例(Singleton)模式是一种广泛使用的设计模式。单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在。一些管理器和控制器常被设计成单例模式。
单例模式的好处:
  • 能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间;
  • 能够避免由于操作多个实例导致的逻辑错误。

单例模式常见模式

饿汉模式

 

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

懒汉模式

懒汉模式的单例,单线程安全版:

但此写法多线程下存在问题:会多次调用构造函数 并未按照懒汉式单例的设计发现有类的静态对象就直接返回此对象,而是多次调用了构造方法创建类的静态对象。原因是多线程调用getInstance方法时,有的线程判断空之后,已经进入了if大括号中,然后时间片被抢,别的线程判断也是空,创建完之后之前的线程拿到cpu直接创建了,导致多次调用构造函数创建。
解决前面饿汉式单例的问题:添加Synchronized关键字

 此方法问题是多个线程试图调用getInstance方法进行判断时都要进行锁定,太降低效率了。缩小加锁范围

实际验证在if内加锁的结果和理论一样 多线程还是会创建多个对象,synchronized关键字放在if里面没有办法解决问题。

DCL懒汉式单例(双重检验Double-Checking-Locking)

双重检验的懒汉式单例,注意给静态对象增加volatile关键字,因为构造函数中的new操作不是原子性操作。

静态内部类

核心:就是将前面类的静态变量的生成过程,即new静态常量的过程放入了静态内部类中,
由于静态内部类是在使用时才加载,就有了懒加载的效果,做到了懒汉式单例的效果,但又不存在加锁的问题。

单例饿汉、懒汉、内部静态类方法总结:

  1. 三种方式都是包含三个部分:public的getInstance方法(给外部提供类的单例对象) 类的静态对象获取 private的类构造器(确保单例)
  2. 都是从getInstance获取单例对象,饿汉是直接返回类的静态常量对象,懒汉是要用双重检验锁 然后返回类的静态常量,静态内部类是直接返回类的静态常量对象
  3. 静态常量的生成 饿汉式直接final static 修饰一个对象获取new类对象 懒汉式是private static volatile声明了一下 然后在getInstance方法中new了 最后返回new的对象 放入方法中实现了延迟加载 静态内部类是搞了一个内部类,把懒汉的那一句声明和实例化都放到静态内部类中了 用静态内部类实现延迟加载
  4. 私有化构造器保证单例,都是在new对象的时候使用到。
posted @   Marktowin  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
点击右上角即可分享
微信分享提示