Java设计模式及应用场景之《单例模式》

article/2025/10/18 13:05:33

文章目录

        • 一、单例模式定义
        • 二、单例模式的结构和说明
        • 三、懒汉式和饿汉式的实现
          • 1、懒汉式
          • 2、饿汉式
        • 四、懒汉式和饿汉式的优缺点
        • 五、双重检查加锁方式的实现
        • 六、类级内部类方式的实现
        • 七、枚举方式的实现 (最佳方式)
        • 八、单例模式的应用场景

一、单例模式定义

保证一个类只能有一个实例,并提供一个访问这个唯一实例的全局访问点。

二、单例模式的结构和说明

在这里插入图片描述
Singleton:负责创建Singleton自己的唯一实例,并提供一个getInstance方法,供外部来访问这个唯一实例。

三、懒汉式和饿汉式的实现

单例模式有两种典型的创建方式,一种叫懒汉式,另一种叫饿汉式。

1、懒汉式

  懒汉式的特点是延迟加载,你不用我就不创建,等到第一次调用的时候,才去创建实例对象。

public class Singleton {//4:定义一个变量来存储创建好的类实例//5:因为这个变量要在静态方法中使用,所以需要加上static修饰private static Singleton instance = null;//1:私有化构造方法,在内部控制创建实例的数目,防止在外部创建实例private Singleton(){}//2:定义一个方法来为客户端提供类实例//3:这个方法需要定义成类方法,也就是要加staticpublic static  Singleton getInstance(){//6:判断存储实例的变量是否有值if(instance == null){//6.1:如果没有,就创建一个类实例,并把值赋值给存储类实例的变量instance = new Singleton();}//6.2:如果有值,那就直接使用return instance;}
}
2、饿汉式

  饿汉式的特点是饥不择食,在加载类的时候就会创建类的实例。

public class Singleton {//4:定义一个静态变量来存储创建好的类实例//直接在这里创建类实例,只会在类加载的时候创建一次private static Singleton instance = new Singleton();//1:私有化构造方法,好在内部控制创建实例的数目private Singleton(){}//2:定义一个方法来为客户端提供类实例//3:这个方法需要定义成类方法,也就是要加staticpublic static Singleton getInstance(){//5:直接使用已经创建好的实例return instance;}
}

四、懒汉式和饿汉式的优缺点

1、时间和空间方面

  • 懒汉式是典型的时间换空间**,每次获取实例时都会去判断是否需要创建实例,浪费判断时间。而如果一直没有人使用的话,就不会去创建实例,节约内存空间。
  • 饿汉式是典型的空间换时间**,当类加载时就会创建实例,不管用不用,先创建出来,再以后调用时,就不需要去判断了,节省了运行时间。

2、线程安全方面

  • 不加同步的懒汉式是线程不安全的,可能会出现并发问题。
  • 饿汉式是线程安全的,因为虚拟机保证只会加载一次,在加载类的时候不会发生并发问题。

五、双重检查加锁方式的实现

  为了解决懒汉式的线程安全问题,我们可以在获取实例方法上加上synchronized,如下:
  public static synchronized Singleton getInstance(){...}
  但是这样会降低整个访问的速度。那么,怎么才能既实现线程安全,又能让性能不受到很大的影响呢?我们可以利用 “双重检查加锁” 的方式来实现。

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

“双重检查加锁” 的方式会用到关键字volatile,这里volatile的作用是防止在创建单例对象时JVM的 指令重排序 。 JVM 为了提高程序的运行效率,会对代码按照 JVM 编译器认为最优的顺序执行,从而可能打乱代码的执行顺序,这也就是我们所说的 指令重排序

我们先来看看我们期望的构建对象的操作指令:

  • 指令1:分配一块内存 M;
  • 指令2:在内存 M 上初始化 Singleton 对象;
  • 指令3:然后将 M 的地址赋值给 instance 变量。

如果不加volatile,JVM 编译器上可能不是这样,可能会被优化成如下指令:

  • 指令1:分配一块内存 M;
  • 指令2:将 M 的地址赋值给 instance 变量;
  • 指令3:在内存 M 上初始化 Singleton 对象。

这个指令重排的优化,就可能会导致线程安全问题。假设线程1刚执行完指令2,此时instance已经不是null了,但是还没有执行指令3对instance对象进行初始化。这时候又来一个线程2,线程2看到instance不是null,直接返回instance,并调用instance的方法或者成员变量,这时将可能触发空指针异常。

六、类级内部类方式的实现

  前面几种方式,都存在小小的缺陷。那么有没有什么方式,既能实现延迟加载,又能实现线程安全呢?类级内部类的方式,就同时实现了延迟加载和线程安全。

public class Singleton {/*** 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例没有绑定关系,* 而且只有被调用到才会装载,从而实现了延迟加载*/private static class SingletonHolder{/*** 静态初始化器,由JVM来保证线程安全*/private static Singleton instance = new Singleton();}/*** 私有化构造方法*/private Singleton(){}public static  Singleton getInstance(){return SingletonHolder.instance;}
}

  当getInstance()方法第一次被调用的时候,SingletonHolder类得到初始化,当SingletonHolder类被加载并初始化时,会初始化它的静态域,从而创建Singleton的实例。由于是静态的域,因此只会在虚拟机加载类的时候初始化一次,并由虚拟机来保证它的线程安全。

七、枚举方式的实现 (最佳方式)

 前面几种方式都有共同的缺点,从而导致多实例的出现。

  • 每次反序列化一个序列化的对象时都会创建一个新的实例。
  • 可以使用反射强行调用私有构造器。

 而枚举类很好的解决了这两个问题,使用枚举除了线程安全和防止反射调用构造器之外,还提供了自动序列化机制,防止反序列化的时候创建新的对象。

单元素的枚举类型已经成为实现单例的最佳方式。

/*** 使用枚举来实现单例模式的示例*/
public enum Singleton {	/*** 定义一个枚举的元素,它就代表了Singleton的一个实例*/INSTANCE;/*** 示意方法,单例可以有自己的操作*/public void singletonOperation(){//功能处理}
}

  使用枚举的方式来实现单例会更加简洁,而且无偿的提供了序列化机制,并由JVM从根本上提供保障,绝对防止多次实例化,是更简洁、高效、安全的实现单例的方式。

八、单例模式的应用场景

  • 网站的计数器,一般是采用单例模式实现,否则难以同步。
  • 应用程序的日志应用,一般都采用单例模式实现,这是由于共享的日志文件一直处于打开状态,只能有一个实例去操作,否则内容不好追加。
  • Web应用的配置文件的读取,一般也采用单例模式,这个是由于配置文件是共享的资源。
  • 数据库连接池的设计一般也是采用单例模式。
  • 多线程的线程池的设计一般也是采用单例模式。
  • 在Spring中创建的Bean实例默认都是单例模式存在的。
  • 在Spring MVC框架中,每个控制器对象也是单例。

http://chatgpt.dhexx.cn/article/XghJosnu.shtml

相关文章

一文带你了解 Java 五种单例模式的实现方式以及应用场景

单例模式 什么是单例模式 类的单例设计模式,就是采取一定的方法保证在整个软件系统中,某个类只能存在一个对象实例,并且这个类会提供一个获取对象实例的方法。 思路:如果让一个类在一个虚拟机里面只能产生一个对象,就…

js设计模式之 单例模式与应用场景

1.介绍 单例模式(Singleton Pattern)是设计模式中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个…

单例模式的理解?单例模式如何实现?单例模式应用场景

说说你对单例模式的理解?如何实现? 一、是什么 单例模式(Singleton Pattern):创建型模式,提供了一种创建对象的最佳方式,这种模式涉及到一个单一的类,该类负责创建自己的对象&…

设计模式之单例模式应用场景篇

应用场景 我们为什么要使用单例模式呢?它有什么好处? (一)单例模式可以让我们只创建一个对象从而避免了频繁创建对象导致的内存消耗和垃圾回收。 Servlet是单例模式,我们只需要创建一个Servlet,然后接收请求…

关于getText()的小问题

由一个作业开始的,整完广度优先小作业的时候开始是在代码中指定值进行寻找路径,后面想想还是弄两文本框输入起点和终点更灵活一点好了。谁知道这个JTextField真的让我崩溃了 怎么说应该是我对Java的基础知识没有进行深入了解吧,好吧,我是在今天才知道getText()是在监听事件…

js gettext

test.php 1 <?php2 $localezh_CN;3 if(isSet($_GET["locale"]))$locale $_GET["locale"];4 ?>5 <html>6 <head>7 <link rel"gettext" type"application/x-po" href"./locale/<?php echo $locale ?&…

关于Java getText()方法的问题

这是一个登陆界面的鼠标事件&#xff0c;获取文本区t61的内容&#xff0c;与用户姓名比对&#xff0c;同时验证登陆密码&#xff0c;但是用户姓名比对一直不成功&#xff0c;导致鼠标事件不能反映&#xff0c;页面不能跳转&#xff0c;想知道为什么&#xff0c;求大佬指点。 p…

java的gettext_JAVA里 getText() 是什么意思,怎么用?

展开全部 JAVA里 getText() 的意思是&#xff1a;返回数据窗口控件中 悬浮在当前行列之上的32313133353236313431303231363533e4b893e5b19e31333431366266编辑框中的文本。 在用户修改数据窗口中某项的值时&#xff0c;实际上首先在悬浮 在当前项上的编辑框中进行修改&#xff…

python gettext的使用方法

app.py 里面的print函数输出内容&#xff0c;是会更据你选择的语言平台而改变 将app.py生成.po文件(或者生成.pot文件)&#xff0c;如果是.pot文件需要重命名为.po pygettext.py安装python的时候就自己带着有&#xff0c;去你的安装路径找 python &#xff08;这一步&#xff…

getText()和getText().toString()

在deadline只有一根咪咪的距离时&#xff0c;我就直接吐槽了。 一个组件&#xff0c;比方说EditView&#xff0c;它的getText()和getText().toString()这两种想得到这个组件中的内容的方法是不一样的&#xff0c;我在用startActivityForResulr()之后接收到来自另一个activity的…

登陆QQ时总显示QQ安全防护进程,而且点了确定后QQ还是登不上

解决办法&#xff1a;把服务QPcore启动&#xff0c;或者删除掉防护进程&#xff08;QPcore&#xff09;

启动电脑QQ遇到QQ安全防护进程,且Windows无法启动QPCore Server

解决方法 1.winR 输入msconfig, “启动”->打开任务管理器 2.最右面的"服务" 3.下面"打开服务" 4.找到Windows update,双击,在"启动类型"选择"自动"→“应用”→“确定” 5.找到QPCore service,双击,在"启动类型"选择&q…

网络安全之应急响应

应急响应(是有一整套流程的)&#xff1a; 原理&#xff1a; 一个组织为了应对各种意外事件的发生所做的准备以及在事件发生后所采取的措施阶段&#xff1a; 准备->启动->抑制->根除->恢复->跟进准备应急工具&#xff0c;相应的应急文档、合同、保密协议&#xf…

操作系统安全实验

缓冲区溢出与数据执行保护DEP实验 实验环境 虚拟机&#xff1a;VirtualBox 6.1.30 操作系统&#xff1a;Ubuntu21.04 主机OS&#xff1a;Microsoft Windows10 实验要求 在关闭数据执行保护机制下&#xff0c;在Linux系统平台上实现缓冲区溢出攻击开启数据执行保护机制&#x…

网络安全教程(2)

目录 4-计算机病毒 4-1认识计算机病毒 4-1-1计算机病毒的概念 4-1-2计算机病毒的特点和分类 5-防火墙 5-1防火墙概述 5-1-1防火墙的概念 5-1-2防火墙的功能 5-1-3防火墙的分类 5-2防火墙主要技术 5-2-1包过滤技术 5-2-2应用代理技术 5-2-3状态检测技术 5-3防火墙体…

Android进程保活拉活

参考&#xff1a;腾讯视频相关视频公开课 学习资料: 探讨Android6.0及以上系统APP常驻内存(保活)实现-争宠篇 目录 一、进程的一些基本常识二、如何保活三、如何拉活四、总结 一、进程的一些基本常识 Low Memory Killer 系统出于体验和性能上的考虑&#xff0c;app在退到后台时…

网络安全之防火墙

目录 网络安全之防火墙 路由交换终归结底是联通新设备 防御对象&#xff1a; 定义&#xff1a; 防火墙的区域划分&#xff1a; 包过滤防火墙 --- 访问控制列表技术 --- 三层技术 代理防火墙 --- 中间人技术 --- 应用层 状态防火墙 --- 会话追踪技术 --- 三层、四层 UTM…

Android进程保活

自己曾经也在这个问题上伤过脑经&#xff0c;前几日刚好有一个北京的哥们在QQ说在做IM类的项目&#xff0c;问我进程保活如何处理比较恰当&#xff0c;决定去总结一下&#xff0c;网上搜索一下进程常驻的方案好多好多&#xff0c;但是很多的方案都是不靠谱的或者不是最好的&…

Android安全防护

各位大佬好&#xff0c;今天谈一下我在实际项目开发中遇到的APP安全以及我做的防护 Android开发者常常面临的一个问题就是防破解、 防二次打包。现如今,安全问题越来越重要,越来越多 的Android开发者也开始寻求安全的保护方案。首先说一下&#xff0c;我做的是保险行业的应用。…