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

java 设计模式之单例模式

简介

单例模式:一个类有且仅有一个实例,该类负责创建自己的对象,同时确保只有一个对象被创建。

特点:类构造器私有、持有自己实例、对外提供获取实例的静态方法。

单例模式的实现方式

饿汉式

类被加载时,就会实例化一个对象并交给自己的引用,供系统使用;而且,由于这个类在整个生命周期中只会被加载一次,因此只会创建一个实例,即能够充分保证单例。

案例:

public class Singleton {private static Singleton instance = new Singleton();private Singleton() { }public static Singleton getInstance() {return instance;}
}

饿汉式比较耗费资源,因为它创建单例的时间过早,它是在类被加载的时候创建单例的

懒汉式加双重检查加锁

饿汉式的优化,只有在获取类的实例时才会创建实例。

案例:

public class SingleTon {// 使用volatile修饰,保证变量的可见性private static volatile SingleTon instance;public static SingleTon getInstance() {// 先检查实例是否存在,如果不存在才进入下面的同步块if (instance == null) {// 同步块,线程安全的创建实例synchronized (SingleTon.class) {// 再次检查实例是否存在,如果不存在才真的创建实例if (instance == null) {instance = new SingleTon();}}}return instance;}
}

饿汉式中的注意事项:

1、为什么类持有的自己的私有实例要用volatile修饰:为了保证指定变量的有序性和可见性。new一个对象的代码 SingleTon instance = new SingleTon(); 可以分解为3行伪代码:

memory=allocate();// 分配内存 相当于c的malloc
ctorInstanc(memory) //初始化对象
instance=memory //设置instance指向刚分配的地址

上面的代码在编译器运行时,可能出现重排序,从 1-2-3 变为 1-3-2,在多线程环境下就会出现问题,使用 volatile 关键字会禁止这种重排序。

2、为什么要双重锁:如果只有一个锁,很有可能两个线程都通过了 if(instance == null) 的判断,所以在进入同步代码块之后还需要再判断一次

用静态内部类来实现单例模式

案例:

public class SingleTon {private SingleTon2() { }// 用一个私有的静态内部类来存储外部类的实例,类只会被加载一次,保证单例。// 内部类只有在被调用时才会被加载,保证了延迟加载private static class SingleTonHolder {private static SingleTon2 instance = new SingleTon2();}public static SingleTon2 getInstance() {return SingleTonHolder.instance;}
}

破坏单例模式

破坏单例模式:序列化和反射可以破坏单例模式。

  • 解决序列化破坏单例的问题:在类中添加readResolve方法,返回类中的实例,可以解决通过序列化破坏单例模式的问题;
  • 解决反射破坏单例的问题:在构造方法中抛异常,可以解决通过反射破坏单例模式的问题

单例模式的使用案例

饿汉式单例模式的使用:jdk中的Runtime类,每个java程序中都只有一个Runtime实例,它代表java程序的运行环境

public class Runtime {// 类被加载时,就会实例化一个对象并交给自己的引用private static Runtime currentRuntime = new Runtime();// 返回单例对象的方法public static Runtime getRuntime() {return currentRuntime;}// 私有化的构造方法/** Don't let anyone else instantiate this class */private Runtime() {}
}

相关文章:

  • 关于 雷达(Radar) 的详细解析,涵盖其定义、工作原理、分类、关键技术、应用场景、挑战及未来趋势,结合实例帮助理解其核心概念
  • 【模型常见评价指标(分类)】
  • 从 ComponentActivity 看 Android Activity 的演变与 Jetpack 架构融合
  • 驱动开发硬核特训 · Day 14:深入理解 Power 管理驱动架构与实战应用
  • SQL Server 存储过程
  • webgl入门实例-08索引缓冲区的基本概念
  • 02、GPIO外设(一):基础知识
  • 3D人脸扫描技术如何让真人“进入“虚拟,虚拟数字人反向“激活“现实?
  • 机器学习在催化剂设计中的应用理论加实操
  • Muduo网络库实现 [十四] - HttpResponse模块
  • 【AI提示词】哲学三问
  • Java基础系列-LinkedList源码解析
  • 面试情景题:企业内部系统如何做微前端拆分,如何通信?
  • IDEA 中 Scala 项目远程连接虚拟机 Spark 环境
  • OpenCV 模板匹配方法详解
  • 中间件--ClickHouse-7--冷热数据分离,解决Mysql海量数据瓶颈
  • springboot自定义starter(避坑教学)
  • OpenCV day5
  • kubernetes-高频率使用命令
  • LeetCode 2176.统计数组中相等且可以被整除的数对:两层遍历模拟
  • 气急败坏!20多名台湾艺人被台当局列为“重点核查对象”
  • 中国情怀:时代记录与家国镜相|澎湃·镜相第三届非虚构写作大赛暨七猫第六届百万奖金现实题材征文大赛征稿启事
  • 师爷、文士、畸人:会稽范啸风及其著述
  • 国防部:菲方应停止一切侵权挑衅危险举动,否则只会自食苦果
  • 河南省委常委会会议:坚持以案为鉴,深刻汲取教训
  • 免签国+1,中乌(兹别克斯坦)互免签证协定6月生效