40岁开始学Java:Java中单例模式(Singleton Pattern),适用场景有哪些?

在这里插入图片描述

在Java中,单例模式(Singleton Pattern)用于确保一个类只有一个实例,并提供全局访问点。以下是详细的实现方式、适用场景及注意事项:


一、单例模式的实现方式

1. 饿汉式(Eager Initialization)

特点:类加载时立即创建实例,线程安全但可能浪费资源。

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

优点:实现简单,线程安全。
缺点:实例在类加载时创建,即使未被使用。


在这里插入图片描述

2. 懒汉式(Lazy Initialization)

特点:延迟实例化,但需处理线程安全问题。

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

优点:按需创建实例。
缺点:同步方法导致性能下降。


3. 双重检查锁(Double-Checked Locking)

特点:减少同步开销,需使用volatile防止指令重排。

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

优点:兼顾线程安全和性能。
缺点:实现较复杂,需注意JDK版本兼容性。


4. 静态内部类(Static Inner Class)

特点:利用类加载机制保证线程安全。

public class InnerClassSingleton {
    private InnerClassSingleton() {}
    
    private static class Holder {
        static final InnerClassSingleton instance = new InnerClassSingleton();
    }
    
    public static InnerClassSingleton getInstance() {
        return Holder.instance;
    }
}

优点:延迟加载,线程安全,无需同步。
缺点:无法通过参数初始化实例。


5. 枚举单例(Enum Singleton)

特点:由JVM保证唯一性,防止反射和序列化破坏。

public enum EnumSingleton {
    INSTANCE;
    
    public void doSomething() {
        // 方法实现
    }
}

优点:天然线程安全,防反射和序列化攻击。
缺点:无法继承其他类,不够灵活。


在这里插入图片描述

二、单例模式的使用场景

  1. 全局配置管理
    例如,系统配置类需要全局唯一实例,确保配置一致。

  2. 日志记录器
    统一管理日志输出,避免多个实例导致资源竞争。

  3. 数据库连接池
    维护唯一的连接池实例,高效管理数据库连接。

  4. 缓存系统
    缓存数据需要全局访问,避免重复创建缓存实例。

  5. 硬件资源访问
    如打印机服务,需统一调度硬件资源。


三、注意事项与潜在问题

  1. 线程安全
    懒汉式需通过同步或双重检查锁确保线程安全。

  2. 反射攻击
    普通单例可能被反射调用构造函数,需在构造器中添加防护:

    private Singleton() {
        if (instance != null) {
            throw new IllegalStateException("Instance already exists");
        }
    }
    
  3. 序列化与反序列化
    实现Serializable接口时,需重写readResolve方法:

    protected Object readResolve() {
        return getInstance();
    }
    
  4. 测试困难
    单例的全局状态可能导致测试耦合,可通过依赖注入(如Spring容器管理)解耦。

  5. 过度使用
    滥用单例会提高代码耦合度,应仅在需要严格唯一实例时使用。


在这里插入图片描述

四、总结

实现方式线程安全延迟加载防反射防序列化适用场景
饿汉式简单场景,实例轻量
懒汉式(同步)需要延迟加载,性能不敏感
双重检查锁高性能要求的延迟加载
静态内部类推荐的延迟加载方式
枚举高安全性要求(推荐方式)

最佳实践

  • 优先选择枚举单例静态内部类实现。
  • 避免通过单例传递全局状态,尽量依赖接口编程。
  • 在框架(如Spring)中,尽量使用容器管理的单例Bean而非手动实现。

通过合理选择实现方式,单例模式能有效管理全局资源,但需谨慎使用以避免设计上的陷阱。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【计算机网络基础】-------计算机网络概念

1.什么是计算机网络 定义: 图解: 2.最简单的计算机网络 其中: 结点可以是计算机、集线器、交换机、路由器等链路可以是有线链路、无线链路 2.1集线器 2.2交换机 3.互连网(internet)与 路由器 路由器 与 家用路由…

Qt 自带颜色属性

Qt 系统自带颜色如下: enum GlobalColor {color0,color1,black,white,darkGray,gray,lightGray,red,green,blue,cyan,magenta,yellow,darkRed,darkGreen,darkBlue,darkCyan,darkMagenta,darkYellow,transparent};对应颜色如下: color0: 这是自定义颜色…

数据结构(初阶)(七)----树和二叉树(前中后序遍历)

实现链式结构的二叉树 实现链式结构的二叉树遍历前序遍历中序遍历后序遍历 节点个数叶子节点个数⼆叉树第k层结点个数⼆叉树的深度/⾼度查找值为X的节点二叉树的销毁 层序遍历判断二叉树是否为完全二叉树 ⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系。 通常…

哔哩哔哩IT私塾python爬虫视频教程中的项目文件

视频链接: Python课程天花板,Python入门Python爬虫Python数据分析5天项目实操/Python基础.Python教程_哔哩哔哩_bilibili 视频教程中要访问的链接: 豆瓣电影 Top 250 httpbin.org seo推广公司网站模板_站长素材 Examples - Apache ECharts WordCloud…

实验:k8s+keepalived+nginx+iptables

1、创建两个nginx的pod,app都是nginx nginx1 nginx2 2、创建两个的pod的service 3、配置两台keepalived的调度器和nginx七层反向代理,VIP设置192.168.254.110 keepalived调度器master keepalived调度器backup 两台调度器都配置nginx七层反向代理&#…

【Cadence仿真学习笔记】ADS Dynamic Link报错model is reserved的解决办法

首先创建好原理图 创建symbol 在library manager下就会出现symbol了 在Cadence的CIW窗口中运行ADS dynamic link 打开ADS后,创建对应的cellview 加入控件OPTIONS 加入网表netlist 这个时候的Netlist没有路径 点击加载symbol 把原来的netlist include删掉…

【星云 Orbit • STM32F4】06. 串口密码:USART 数据传递

1. 引言 STM32F407是一款高性能的微控制器,具有丰富的外设和强大的处理能力。串口(USART)是STM32F407的重要外设之一,广泛应用于数据通信、调试和控制等领域。本教程旨在帮助小白从零开始,手动配置STM32F407的串口功能…

Win32 C++ 电源计划操作

CPowerCfgUtils.h #pragma once#include <Windows.h> #include <powrprof.h>// https://learn.microsoft.com/zh-cn/windows/win32/api/powrprof/?sourcerecommendations//节能 //DEFINE_GUID(GUID_MAX_POWER_SAVINGS, 0xA1841308, 0x3541, 0x4FAB, 0xBC, 0x81, …

MySQL—使用binlog日志恢复数据

一、binlog日志恢复数据简介 在 MySQL 中&#xff0c;使用二进制日志&#xff08;binlog&#xff09;恢复数据是一种常见的用于故障恢复或数据找回的方法。以下是详细的使用步骤&#xff1a; 确认 binlog 已启用&#xff1a;首先需要确认 MySQL 服务器已经启用了二进制日志功…

基于springboot+vue实现的宠物救助及领养平台(源码+L文+ppt)43-21

摘 要 宠物救助及领养平台是一个专注于宠物保护和幸福的在线平台。它致力于连接那些需要帮助的宠物与愿意给予它们关爱的家庭。通过这个平台&#xff0c;人们可以报告丢失的宠物、寻求救助资源&#xff0c;以及浏览可领养的宠物信息。该平台不仅提供了一个渠道&#xff0c;让…

人大金仓国产数据库与PostgreSQL

一、简介 在前面项目中&#xff0c;我们使用若依前后端分离整合人大金仓&#xff0c;在后续开发过程中&#xff0c;我们经常因为各种”不适配“问题&#xff0c;但可以感觉得到大部分问题&#xff0c;将人大金仓视为postgreSQL就能去解决大部分问题。据了解&#xff0c;Kingba…

【Java分布式】Nacos注册中心

Nacos注册中心 SpringCloudAlibaba 也推出了一个名为 Nacos 的注册中心&#xff0c;相比 Eureka 功能更加丰富&#xff0c;在国内受欢迎程度较高。 官网&#xff1a;https://nacos.io/zh-cn/ 集群 Nacos就将同一机房内的实例划分为一个集群&#xff0c;一个服务可以包含多个集…

派可数据BI接入DeepSeek,开启智能数据分析新纪元

派可数据BI产品完成接入DeepSeek&#xff0c;此次接入标志着派可数据BI在智能数据分析领域迈出了重要一步&#xff0c;将为用户带来更智能、更高效、更便捷的数据分析体验。 派可数据BI作为国内领先的商业智能解决方案提供商&#xff0c;一直致力于为用户提供高效、稳定易扩展…

【漫话机器学习系列】110.线性可分(Linearly Separable)

线性可分与线性不可分的概念详解 1. 引言 在机器学习和模式识别领域&#xff0c;分类问题是一个重要的研究方向。在分类任务中&#xff0c;我们通常需要将不同类别的数据点分开&#xff0c;而如何进行分割是一个关键问题。线性可分&#xff08;Linearly Separable&#xff09…

架构师面试(九):缓存一致性

问题 关于【数据库和缓存】一致性&#xff0c;下面哪几项是在线上生产环境中相对合理的处理方式&#xff1f; A. 对于查询操作&#xff0c;先查缓存&#xff0c;如果为空则查 DB&#xff0c;然后将数据带入缓存&#xff1b; B. 对于插入操作&#xff0c;只写 DB 即可&#…

LearnOpenGL之Shader编程用算法绘画

———————————————————— 前序 ——————————————————— AndroidLearnOpenGL是本博主自己实现的LearnOpenGL练习集合&#xff1a; Github地址&#xff1a;GitHub - wangyongyao1989/AndroidLearnOpenGL: OpenGL基础及运用 系列文章&#xff…

基于 Flink CDC YAML 的 MySQL 到 Kafka 流式数据集成

本教程的演示都将在 Flink CDC CLI 中进行&#xff0c;无需一行 Java/Scala 代码&#xff0c;也无需安装 IDE。 这篇教程将展示如何基于 Flink CDC YAML 快速构建 MySQL 到 Kafka 的 Streaming ELT 作业&#xff0c;包含整库同步、表结构变更同步演示和关键参数介绍。 准备阶段…

【Maven】基于IDEA进行Maven工程的创建、构建

文章目录 一、基于IDEA创建Maven工程1. 概念梳理Maven工程的GAVP2. Idea构建Maven Java SE工程3. Idea构建Maven Java Web工程3.1 创建一个maven的javase工程3.2 修改pom.xml文件打包方式3.3 设置web资源路径和web.xml路径 4. Maven工程项目结构说明 二、基于IDEA进行Maven工程…

计算机毕业设计SpringBoot+Vue.js在线课程管理系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

【爬虫基础】第二部分 爬虫基础理论 P3/3

上节内容回顾&#xff1a;【爬虫基础】第一部分 网络通讯 P1/3-CSDN博客 【爬虫基础】第一部分 网络通讯-Socket套接字 P2/3-CSDN博客 【爬虫基础】第一部分 网络通讯-编程 P3/3-CSDN博客 【爬虫基础】第二部分 爬虫基础理论 P1/3-CSDN博客 【爬虫基础】第二部分 爬虫基础理论…