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

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

单例模式

什么是单例模式

类的单例设计模式,就是采取一定的方法保证在整个软件系统中,某个类只能存在一个对象实例,并且这个类会提供一个获取对象实例的方法。

思路:如果让一个类在一个虚拟机里面只能产生一个对象,就必须将构造器的访问权限设置为private,这样在外部,就不能new这个对象了,只能在内部实例化这个对象。因为外部 不能获取,所以可以通过调用一个静态方法,返回类的内部创建的静态对象。

两大种实现方式

饿汉式

饿汉式实现举例

package com.designPattren;/*** 饿汉式单例模式*/
public class SingleHungry {private static final SingleHungry SINGLE_HUNGRY_INSTANCE = new SingleHungry();/*** 防止反射破坏单例*/private SingleHungry() {if (SINGLE_HUNGRY_INSTANCE != null) {throw new RuntimeException("不能重复创建单例");}System.out.println("singleton");}public static SingleHungry getInstance() {return SINGLE_HUNGRY_INSTANCE;}/*** 重写readResolve方法,防止反序列化破坏单例* @return*/public Object readResolve() {return SINGLE_HUNGRY_INSTANCE;}/*** 测试方法,懒汉还是饿汉式*/public static void otherMethod() {System.out.println("aaaaaa");}}

注意:如果构造方法不对单例对象是否实现进行判断,单例就可能被反射破坏;
readResolve方法的重写是防止反序列化破坏单例,重写这个方法之后反序列化就不返回字节数组了,返回这个单例对象。
使用这种方式创建单例对象,是不能方式Unsafe破坏单例的

枚举式饿汉:


/*** 枚举类创建单例*/
public enum SingletonHungryBuEnum {INSTANCE;SingletonHungryBuEnum() {System.out.println("singleton");}public SingletonHungryBuEnum getInstance() {return INSTANCE;}public void otherMethod() {System.out.println("aaaaa");}}

枚举饿汉式能天然防止反射、反序列化破坏单例

懒汉式

懒汉式不同于饿汉式,懒汉式单例只有调用这个单例对象的时候才创建对象。

public class Singleton3 implements Serializable {private Singleton3() {System.out.println("private Singleton3()");}private static Singleton3 INSTANCE = null;// Singleton3.classpublic static synchronized Singleton3 getInstance() {if (INSTANCE == null) {INSTANCE = new Singleton3();return INSTANCE;}
//这里为了测试类初始化的时候,是否调用构造方法,如果调用了构造方法,也就意味着对象被初始化了public static void otherMethod() {System.out.println("otherMethod()");}}

这样锁粒度太大了。实际上需要同步的时候只是在首次创建单例对象的时候。所以可以改进一下

双检锁懒汉式

public class Singleton4 implements Serializable {private Singleton4() {System.out.println("private Singleton4()");}private static volatile Singleton4 INSTANCE = null; // 可见性,有序性public static Singleton4 getInstance() {if (INSTANCE == null) {synchronized (Singleton4.class) {if (INSTANCE == null) {INSTANCE = new Singleton4();}}}return INSTANCE;}public static void otherMethod() {System.out.println("otherMethod()");}
}

前文我们加锁是在整个getInstance方法上加锁,但是粒度太大了。我们只需要在创建新对象的时候加锁就可以了。但是如果只有第一层
INSTANCE == null判断,那么可能会出现下面的问题:A线程占有资源B进程挂起,但是if判断B线程是可以进去的,A释放资源之后B又创建新对象了,为了避免这种问题,我们在同步代码快里面再加一个判断。双检机制解决了重复创建对象的问题。
但是这并不是完全安全的,在整个对象创建的过程,其实是分三步的,创建对象,调用构造方法,给静态变量赋值。创建对象毋庸置疑是第一步执行的,但是后面两步,它实际上先后执行的顺序是不确定的。JVM可能 先putstatic,在执行构造方法init对象。如果先putstatic,那么当前单例对象就不是空了,其他线程在这个时候如果来获取单例对象,就可能获取到未被构造方法初始化的对象。为了避免这种问题,在单例对象上加volatile关键字。保证单例对象的有序性。加关键字之后,执行构造方法这一步骤就会加上内存屏障,putstatic只能在构造方法init对象之后才能执行。避免了指令重排序。解决了上述的问题。

内部类懒汉式

内部类相较于上述实现方法,实现比较简单,利用静态内部类的特性。只有在首次使用静态内部类的时候静态内部类才会加载。这样我们在实现单例的时候只要把单例对象定义在内部类里,当调用getInstance的时候,静态内部类的静态变量就实例化。静态变量的初始化是在静态代码块里面的,天然的避免了线程安全。

public class Test {public static void main(String[] args) {otherMethod();System.out.println("-----------------------");/*Test instance = new Test().getInstance();System.out.println(instance == null ? "1" : "0");*/}Test() {System.out.println("go To init");}static class a{private static final Test INSTANCE = new Test();}   public static Test getInstance() {return a.INSTANCE;}/*** 测试是否调用构造方法,看这个变量有没有先创建。*/public static void otherMethod() {System.out.println("om");}}

在JDK中的体现。

java.lang.RunTime 典型的饿汉式单例创建
在这里插入图片描述
java.io.Console 双捡锁懒汉式单例模式
在这里插入图片描述

  • Collections 中的 EmptyNavigableSet 内部类懒汉式单例
    在这里插入图片描述

  • ReverseComparator.REVERSE_ORDER 内部类懒汉式单例

  • Comparators.NaturalOrderComparator.INSTANCE 枚举饿汉式单例


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

相关文章

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;我做的是保险行业的应用。…

多进程浏览器浅析

多进程的浏览器 对QQ浏览器的测试&#xff1a; 在打开八个网页页面之后&#xff0c;在任务管理器界面察看详细信息&#xff1a; 可以得知现在的浏览器应该都是多进程实现的。 那么为什么使用多进程来实现浏览器&#xff1f; 首先看一下进程与线程的区别&#xff1a; **进…