java设计模式 单例模式

news2025/1/8 0:57:04

单例模式

什么是单例模式

单例模式(Singleton Pattern)是一种设计模式,目的是确保一个类在整个程序中只有一个实例,并提供一个全局的访问点来获取该实例。它常用于需要频繁访问某个对象的场景,且该对象在整个程序运行过程中只需一个实例时。

单例模式的用途

单例模式的主要用途包括:

控制资源共享:在许多应用场景下,某个类的实例可能是资源密集型的或占用大量内存的,单例模式确保只有一个实例存在,避免了不必要的资源浪费。
全局访问点:它为应用程序中的某些全局状态提供了一个访问点,例如,数据库连接池、日志管理器、配置管理等。
跨多个组件共享数据或状态:通过单例模式,所有组件可以访问到相同的实例,确保数据一致性和共享状态。
避免重复创建:对于一些创建成本较高的对象,可以确保只创建一次并重复使用,降低了程序的开销。

单例模式的写法

饿汉式

饿汉式是类加载时就创建实例,不论是否使用,通常适用于实例化过程简单且没有线程安全问题的情况。

public class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {}  // 私有构造函数,防止外部创建实例

    public static Singleton getInstance() {
        return instance;
    }
}


懒汉式

懒汉式是在第一次使用时才创建实例,延迟加载,但它的缺点是线程不安全,在多线程环境中可能会出问题。
例如多个线程获取这个单例对象的时候会先执行static静态方法,当多个线程同时进入getInstance方法因为没加锁,所以可能创建多个Singleton对象

public class Singleton {
    private static Singleton instance;

    private Singleton() {}  // 私有构造函数,防止外部创建实例

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

线程安全的懒汉式

通过加锁确保线程安全。虽然可以解决多线程问题,但由于每次获取实例时都要进行同步,可能会导致性能瓶颈。

public class Singleton {
    private static Singleton instance;

    private Singleton() {}  // 私有构造函数,防止外部创建实例

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

双重检验锁

双重检查锁定是懒汉式的优化版本,只有第一次创建实例时加锁,后续访问时不再加锁,避免了性能问题。

public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}  // 私有构造函数,防止外部创建实例

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

静态内部类

静态内部类是线程安全的懒加载方式,它利用 Java 类加载机制确保线程安全,并且延迟加载

public class Singleton {
    private Singleton() {}  // 私有构造函数,防止外部创建实例

    private static class SingletonHelper {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHelper.INSTANCE;
    }
}

解释:

SingletonHelper 类是静态的,并且只会在 getInstance() 方法第一次调用时加载,因此确保了延迟加载和线程安全。
这种方式不仅线程安全,而且性能较高,是推荐的单例模式实现方法。

由于类加载的过程是线程安全的,JVM 会保证只会有一个线程加载类,并且保证初始化过程不会被多次执行。

单例模式的应用场景

单例模式的应用非常广泛,常见的地方包括:

数据库连接池:为了提高数据库连接的复用性,避免频繁创建和销毁数据库连接对象,数据库连接池通常会使用单例模式。

日志管理器:日志对象通常是单一的,不需要多个实例来记录日志,单例模式确保日志管理器在整个程序中只有一个实例。

配置管理:应用程序的配置通常是唯一的,使用单例模式来读取和管理配置文件,避免多次加载配置。

线程池管理:为了避免多次创建线程池,线程池管理对象通常使用单例模式来保证系统中只存在一个线程池实例。

缓存管理:许多应用需要使用缓存来提高性能,缓存对象可以使用单例模式,保证缓存数据一致性。

应用程序上下文(AppContext):有些框架或大型系统中,常用单例模式管理应用程序的上下文信息,如Spring框架中的应用上下文。

在我们使用的Springboot框架中,springboot中的注解例如@Controller @Service @Repository都是spring容器给我们管理创建的饿汉式单例对象

数据库连接池

在 Spring Boot 中,数据库连接池(如 HikariCP,默认的连接池)通过单例模式来管理的。在 application.yml 或 application.properties 文件中配置数据库连接池的属性时,Spring Boot 会将这些配置应用到数据库连接池的实例中。

Spring Boot 会在启动时初始化数据库连接池,并且通常会作为一个 单例 Bean 存在,避免了每次需要连接数据库时都重新创建连接池的开销。这个单例的数据库连接池会被应用程序的所有数据库操作共享,从而提高了数据库连接的复用性和效率。

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver  # 这个通常是可以省略的,Spring Boot 会自动推断
    hikari:
      maximum-pool-size: 10  # 连接池配置

Spring Boot 会根据这些配置自动创建并初始化数据库连接池,并将其作为单例 Bean 注入到 Spring 容器中。

日志配置

在 Spring Boot 中,日志对象(如 Logger)是通过 LoggerFactory 来创建的,且通常是单例的。日志管理器是一个典型的应用场景,其中日志对象不需要多个实例,因此使用单例模式来确保在整个应用程序中只有一个实例。

配置管理类

Spring Boot 会根据配置文件中的内容自动创建一个配置类,加载配置并将其作为一个单例 Bean 提供给应用程序。
在 Spring Boot 启动时,DataSourceConfig 会作为一个单例 Bean 被加载,并且能够共享整个应用的数据库配置。

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceConfig {
    private String url;
    private String username;
    private String password;
    // getters and setters
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2272928.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用VS C#构建Windows服务【纯操作版,附带项目地址】

1.点击“创建新项目”,选择“Windows 服务(.NET Framework)” 2、给项目命名 3、双击“Service1.cs”,右键,选择“添加安装程序”,就会生成一个“ProjectInstaller.cs”文件 4、双击“P…

KUKA机器人如何修改程序并下载到机器人控制器中?

KUKA机器人如何修改程序并下载到机器人控制器中? 如下图所示,首先将使用的网卡的IP地址设置为自动获得, 打开workvisual软件,点击搜索,正常情况下可以搜索到项目文件,选中后双击进入, 如下图所示,此时,workvisual会自动从机器人控制器中下载项目文件到电脑上,耐心等待…

L28.【LeetCode笔记】移动零(三种解法)

目录 1.题目 2.向前覆盖法 分析 代码 提交结果 3.优解:双指针 代码 提交结果 4.其他不符合题意的方法:使用队列 代码 提交结果 1.题目 https://leetcode.cn/problems/move-zeroes/description/ 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾…

js逆向实战(1)-- 某☁️音乐下载

下载某云音乐源文件.mp4格式 首先随便点进一首歌,如图所示获取该音乐id,然后点击播放键,打开F12进行查询XHR 由此可知,实际请求网址是 https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token「你的token」url需带…

深入了解 SSL/TLS 协议及其工作原理

深入了解 SSL/TLS 协议及其工作原理 一. 什么是 SSL/TLS?二. SSL/TLS 握手过程三. SSL/TLS 数据加密与传输四. 总结 点个免费的赞和关注,有错误的地方请指出,看个人主页有惊喜。 作者:神的孩子都在歌唱 一. 什么是 SSL/TLS? 安全套接层&am…

Java四大常用JSON解析性能对比:Hutool、Fastjson2、Gson与Jackson测试

1. 引言 JSON 是现代软件开发中常用的数据交换格式,尤其在微服务和前后端分离的架构中更是必不可少。 本文将对 Java 中四大主流 JSON 解析库——Hutool、Fastjson2、Gson 和 Jackson 进行性能测试和对比分析,通过实测 20 万条数据解析,揭示…

【整理集合大全】MySQL(4) 数据库增删改查SQL语句

查看数据库 show databases; 使用数据库 use 数据库名;创建数据库 CREATE DATABASE 数据库名;删除数据库 DROP DATABASE 数据库名;创建表 create table 表名(列名1 类型(长度) [约束],列名2 类型(长度) [约束],…… );长度区别 int类型带长度:不影响存取值&…

升级 Spring Boot 3 配置讲解 —— Spring Boot 3 核心源码专讲

学会这款 🔥全新设计的 Java 脚手架 ,从此面试不再怕! Spring Boot 3 是 Spring 生态中的重要里程碑,它不仅全面支持 Java 17,还引入了许多新特性,如对 GraalVM 原生镜像的支持、改进的性能优化以及更灵活的…

vue3中el-table实现多表头并表格合并行或列

1、el-table中添加事件 :span-method"genderSpanCity" <el-table :span-method"genderSpanCity":data"data.tableData":fit"true" table-layout"fixed" header-align"center" stripestyle"width:100%;he…

OpenGL —— 流媒体播放器 - ffmpeg解码rtsp流,opengl渲染yuv视频(附源码,glfw+glad)

效果 说明 FFMpeg和OpenGL作为两大技术巨头,分别在视频解码和图形渲染领域发挥着举足轻重的作用。本文将综合两者实战视频播放器,大概技术流程为:ffmpeg拉取rtsp协议视频流,并经过解码、尺寸格式转换为yuv420p后,使用opengl逐帧循环渲染该yuv实时视频。 核心源码 vertexSh…

Web安全扫盲

1、建立网络思维模型的必要 1 . 我们只有知道了通信原理&#xff0c; 才能够清楚的知道数据的交换过程。 2 . 我们只有知道了网络架构&#xff0c; 才能够清楚的、准确的寻找漏洞。 2、局域网的简单通信 局域网的简单通信&#xff08;数据链路层&#xff09; 一般局域网都通…

HTML 显示器纯色亮点检测工具

HTML 显示器纯色亮点检测工具 相关资源文件已经打包成html等文件&#xff0c;可双击直接运行程序&#xff0c;且文章末尾已附上相关源码&#xff0c;以供大家学习交流&#xff0c;博主主页还有更多Html相关程序案例&#xff0c;秉着开源精神的想法&#xff0c;望大家喜欢&#…

ARM发布Armv9.5架构:迈向更强性能与灵活性的新时代

2024年11月30日&#xff0c;ARM正式发布了其最新的Armv9.5架构&#xff0c;这是Arm技术发展的又一重要里程碑。从表中信息来看&#xff0c;Armv9.5架构的发布标志着该公司的架构系列在性能、灵活性和可扩展性方面取得了进一步突破。本次发布不仅是技术上的提升&#xff0c;更是…

被催更了,2025元旦源码继续免费送

“时间从来不会停下&#xff0c;它只会匆匆流逝。抓住每一刻&#xff0c;我们才不会辜负自己。” 联系作者免费领&#x1f496;源&#x1f496;码。 三联支持&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;亲爱的朋友们&#xff0c;感谢你…

【Rust自学】10.4. trait Pt.2:trait作为参数和返回类型、trait bound

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 说句题外话&#xff0c;写这篇的时间比写所有权还还花的久&#xff0c;trait是真的比较难理解的概念。 10.4.1. 把trait作为参数 继续以…

R机器学习:神经网络算法的理解与实操,实例解析

神经网络算法是一种模仿生物神经网络&#xff08;尤其是人脑&#xff09;结构和功能的算法。它由大量相互连接的节点&#xff08;称为神经元&#xff09;组成&#xff0c;这些神经元组织成层&#xff0c;通过传递信号来处理信息。神经网络算法在机器学习、人工智能等领域中扮演…

Java(day4)

二维数组 静态初始化 动态初始化 练习 public class test1 {public static void main(String[]args){int arr[][]{{22,66,44},{77,33,88},{25,45,65},{11,66,99}};int sum0;for(int i0;i<arr.length;i){int a0;for(int j0;j<arr[i].length;j){sumarr[i][j];aarr[i][j];…

element-plus大版本一样,但是小版本不一样导致页面出bug

npm 的版本 node的版本 npm的源这些都一样&#xff0c;但是效果不一样 发现是element的包版本不一样导致的 2.9.1与2.8.1的源是不一样的&#xff0c;导致页面出bug;

【Docker】安装registry本地镜像库,开启Https功能

下载镜像 docker pull registry:2 需要启动https功能&#xff0c;就要生成服务端的自签名的证书和私钥&#xff0c;以及在docker客户端安装这个经过签名的证书。 第一步&#xff1a;生成公私钥信息&#xff0c;第二步&#xff0c;制作证书签名申请文件&#xff0c; 第三步&…

单片机-LED点阵实验

要将第一个点点亮&#xff0c;则 1 脚接高电平 a 脚接低电平&#xff0c;则第一个点就亮了&#xff1b;如果要将第一行点亮&#xff0c;则第 1 脚要接高电平&#xff0c;而&#xff08;a、b、c、d、e、f、g、h &#xff09;这些引脚接低电平&#xff0c;那么第一行就会点亮&…