设计模式之美学习-创建型-单例模式(十五)
说明
从业务概念上,有些数据在系统中只应该保存一份,就比较适合设计为单例类。比如,系统的配置信息类。除此之外,我们还可以使用单例解决资源访问冲突的问题。
饿汉式
在类加载的时候就创建
public class IdGenerator { private AtomicLong id = new AtomicLong(0); //2.类加载的时候就初始化 private static final IdGenerator instance = new IdGenerator(); //1.构造函数私有化 private IdGenerator() { } //3.提供一个公共的静态方法 public static IdGenerator getInstance() { return instance; } public long getId() { return id.incrementAndGet(); } }
懒汉式
普通版本
public class IdGenerator { private AtomicLong id = new AtomicLong(0); private static IdGenerator instance; //构造哈数私有化 private IdGenerator() { } //加锁 避免并发的时候多次创建 public static synchronized IdGenerator getInstance() { if (instance == null) { instance = new IdGenerator(); } return instance; } public long getId() { return id.incrementAndGet(); } }
缺点:方法加了同步锁避免多线程并发 重复创建,但是当初始化后每次获取都会获取锁,性能不好
双重检测
public class IdGenerator { private AtomicLong id = new AtomicLong(0); private static volatile IdGenerator instance; //构造函数私有化 private IdGenerator() {} public static IdGenerator getInstance() { if (instance == null) { synchronized(IdGenerator.class) { // 此处为类级别的锁 //二次判断是为了防止多线程在同步锁等待 第一个释放后 其余进入锁 会重复创建 if (instance == null) { instance = new IdGenerator(); } } } return instance; } public long getId() { return id.incrementAndGet(); } }
静态内部类
public class IdGenerator { private AtomicLong id = new AtomicLong(0); //构造函数私有化 private IdGenerator() {} //加载IdGenerator时SingleonHoldre并不会加载 private static class SingletonHolder{ private static final IdGenerator instance = new IdGenerator(); } //调用get方你发触发holder加载 public static IdGenerator getInstance() { return SingletonHolder.instance; } public long getId() { return id.incrementAndGet(); } }
防止单列模式被破坏
1、防止反射破环(虽然构造方法已私有化,但通过反射机制使用newInstance()方法构造方法也是可以被调用):
- 首先定义一个全局变量开关isFristCreate默认为开启状态
- 当第一次加载时将其状态在更改为关闭状态
2、防止克隆破环
- 重写clone(),直接返回单例对象
3、防止序列化破环
- 添加readResolve(),返回Object对象
public class Singleton implements Serializable,Cloneable{ private static final long serialVersionUID = 6125990676610180062L; private static Singleton singleton; private static boolean isFristCreate = true;//默认是第一次创建 private Singleton(){ if (isFristCreate) { synchronized (Singleton.class) { if (isFristCreate) { isFristCreate = false; } } }else{ throw new RuntimeException("已然被实例化一次,不能在实例化"); } } public void doAction(){ //TODO 实现你需要做的事 } public static Singleton getInstance(){ if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } @Override protected Singleton clone() throws CloneNotSupportedException { return singleton; } private Object readResolve() { return singleton; } }
摘自:https://www.cnblogs.com/call-me-pengye/p/11169051.html
使用枚举
/** * 使用 IdGenerator.instance.getId(); */ public enum IdGenerator { instance; private AtomicLong id = new AtomicLong(0); public long getId() { return id.incrementAndGet(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!