总结单例模式的写法

news2024/9/25 23:15:46

一、单例模式的概念

1.1 单例模式的概念

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。就是当前进程确保一个类全局只有一个实例。

1.2  单例模式的优点

  • 单例模式在内存中只有一个实例,减少了内存开支
  • 单例模式只生成一个实例,所以减少了系统的性能开销
  • 单例模式可以避免对资源的多重占用
  • 单例模式可以在系统设置全局的访问点

1.3 单例模式的缺点

  • 单例模式一般没有接口,扩展很困难
  • 单例模式不利于测试
  • 单例模式与单一职责原则有冲突

1.4 使用场景

  • 要求生成唯一序列号的环境
  • 在整个项目中需要一个共享访问点或共享数据
  • 创建一个对象需要消耗的资源过多
  • 需要定义大量的静态常量和静态方法(如工具类)的环境

2.懒汉式

懒汉式,顾名思义就是实例在用到的时候才去创建,“比较懒”,用的时候才去检查有没有实例,如果有则直接返回,没有则新建。


2.1 懒汉式(加锁)


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

 这种把锁直接方法上的办法,所有的访问都需要获取锁,导致了资源的浪费。

2.2 懒汉式(双重校验锁)

public class Singleton{
    //volatile修饰,防止指令重排
    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;
    }

}

我们把synchronized加在了方法的内部,一般的访问是不加锁的,只有在instance==null的时候才加锁。

(1)为什么要双重校验?

如果不双重校验。

如果两个线程一起调用getInstance方法,并且都通过了第一次的判断instance==null,那么第一个线程获取了锁,然后实例化了instance,然后释放了锁,然后第二个线程得到了线程,然后马上也实例化了instance。这就不符合我们的单例要求了。

(2)为什么要用volatile 修饰 instance?

防止指令重排。

那这个重排指的是哪?指的是instance = new Singleton(),我们感觉是一步操作的实例化对象,实际上对于JVM指令,是分为三步的:

  • 分配内存空间
  • 初始化对象
  • 将对象指向刚分配的内存空间

有些编译器为为了性能优化,可能会把第二步和第三步进行重排序,顺序就成了:

  • 分配内存空间
  • 将对象指向刚分配的内存空间
  • 初始化对象

3. 饿汉式

饿汉式,就像它的名字,饥不择食,定义的时候直接初始化。

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

因为instance是个静态变量,所以它会在类加载的时候完成实例化,不存在线程安全的问题。

这种方式不是懒加载,不管我们的程序会不会用到,它都会在程序启动之初进行初始化。

4. 静态内部类

静态内部类是更进一步的写法,不仅能实现懒加载、线程安全,而且JVM还保持了指令优化的能力。

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

Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会加载静态内部类InnerSingleton类,从而完成Singleton的实例化。

类的静态属性只会在第一次加载类的时候初始化,同时类加载的过程又是线程互斥的,JVM帮助我们保证了线程安全。

5. 枚举

通过enum修饰Singleton单例类,仅需定义一个INSTANCE,然后在静态方法实例化方法getInstance中直接返回INSTANCE即可。

public enum Singleton {
    INSTANCE;
    public static Singleton getInstance(){
        return INSTANCE;
    }
}

6 总结


饿汉模式:线程是安全的,只进行读操作
懒汉模式:不安全,有读操作也有写操作

单例模式的选择取决于具体需求,如是否需要懒加载、是否需要线程安全等。每种实现方式都有其适用场景和潜在问题,设计时应根据具体情况选择最合适的实现方法。

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

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

相关文章

【postgresql】时间函数和操作符

日期/时间操作符 加减操作符: 和 - 可以用于日期、时间、时间戳和时间间隔的加减操作。 SELECT 2024-01-01::date INTERVAL 1 day as "date"; ; -- 结果:2024-01-02SELECT 2024-01-01 12:00:00::timestamp - INTERVAL 2 hours as "…

泽众一站式性能测试平台P-One监控指标的意义

在当今数字化和信息化高度发展的时代,企业把保障系统稳定运行、优化业务流程和提升用户体验摆在首要位置。然而,在现如今复杂的分布式系统中,各个组件和服务之间的交互频繁且紧密,当系统出现性能瓶颈时,传统的监测手段…

Flutter 初识:导航控件

Flutter导航控件小结 路由与导航Navigator核心方法属性示例基本导航示例替换当前页面并推入新页面使用命名路由动态生成路由额外的导航功能 完整示例代码 MaterialPageRoute属性示例 CupertinoPageRoute属性示例 应用栏与底部导航AppBar属性解析示例 BottomNavigationBar属性解…

gorm只查询某一些字段字段的方法Select, 和只查询某一字段方法 Pluck

gorm中默认是查询所有字段的, 如果我们只需要获取某些字段的值,可以通过使用 Select方法来指定要查询的字段来实现, 也可以通过定义一个需要字段的结构体来实现; 而如果我们只需要查询某一个字段的值就可以使用 Pluck方法来获取(这…

【Python】一文向您详细介绍 `isinstance()` 的原理、作用和使用场景

【Python】一文向您详细介绍 isinstance() 的原理、作用和使用场景 下滑即可查看博客内容 🌈 欢迎莅临我的个人主页 👈这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地!🎇 🎓 博主简介:985…

【精品资料】数字乡村一体化解决方案(45页PPT)

引言:数字乡村一体化解决方案是响应国家乡村振兴战略,依托现代信息技术和数字经济理念,对乡村进行全面改造和升级的综合框架。该方案旨在通过数字化手段,推动乡村产业、治理、文化、教育、医疗等领域的协同发展,实现乡…

2024年【通信安全员ABC证】实操考试视频及通信安全员ABC证考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2024年通信安全员ABC证实操考试视频为正在备考通信安全员ABC证操作证的学员准备的理论考试专题,每个月更新的通信安全员ABC证考试试题祝您顺利通过通信安全员ABC证考试。 1、【单选题】.重大事故一般由事故…

智慧水利解决方案:从理论到实践的全面跨越,展示其在水资源管理、水灾害预警、水生态保护等方面的创新应用

目录 一、引言:智慧水利的时代背景与意义 二、智慧水利的理论框架与技术体系 1、理论框架 2、技术体系 三、智慧水利在水资源管理中的应用 1、水资源优化配置 2、水量水质协同管理 四、智慧水利在水灾害预警中的应用 1、洪水预警与应急响应 2、干旱监测与评…

【学党史、悟思想、办实事、开新局】学习《中国共产党历史》一、鸦片战争与近代中国社会的演变

历史是最好的教科书。学习党史、国史,是坚持和发展中国特色社会主义、把党和国家各项事业继续推向前进的必修课。 而我们作为普通群众,学习跟了解历史是我觉得可以做到的最基本东西,从前有过一段时间对历史特感兴趣,如中国古代史…

AI算法15-弹性网络回归算法Elastic Net Regression | ENR

弹性网络回归算法简介 在机器学习领域中,弹性网络(Elastic Net)是一种结合了L1范数(套索回归)和L2范数(岭回归)的正则化方法。它综合了两者的优点,既可以实现特征选择,又…

从“卷模型”到“卷应用”:AI时代的价值重塑与个性化智能探索

🌈所属专栏:【其它】✨作者主页: Mr.Zwq✔️个人简介:一个正在努力学技术的Python领域创作者,擅长爬虫,逆向,全栈方向,专注基础和实战分享,欢迎咨询! 您的点…

Java基础之集合

集合和数组的类比 数组: 长度固定可以存基本数据类型和引用数据类型 集合: 长度可变只能存引用数据类型存储基本数据类型要把他转化为对应的包装类 ArrayList集合 ArrayList成员方法 添加元素 删除元素 索引删除 查询 遍历数组

mqtt.fx连接阿里云

本文主要是记述一下如何使用mqtt.fx连接在阿里云上创建好的MQTT服务。 1 根据MQTT填写对应端口即可 找到设备信息,里面有MQTT连接参数 2 使用物模型通信Topic,注意这里的post说设备上报,那也就是意味着云端订阅post;set则意味着设…

向量索引【草稿】

用「向量」化数据表示「概念」。 向量表达:概念上更为接近的点在空间中更为聚集,而概念上更为不同的点,则距离更远。 向量数学表达:以坐标原点为起点,这些坐标点重点。 在语言上应用–词向量。 一个训练恰当的词向量集合,将和指代的事物之间的向量集合十分接近。有利于自…

记一次 .NET某上位视觉程序 离奇崩溃分析

一:背景 1. 讲故事 前段时间有位朋友找到我,说他们有一个崩溃的dump让我帮忙看下怎么回事,确实有太多的人在网上找各种故障分析最后联系到了我,还好我一直都是免费分析,不收取任何费用,造福社区。 话不多…

IDEA启动Web项目总是提示端口占用

IDEA启动Web项目总是提示端口占用 一、前言 1.场景 IDEA启动Web项目总是提示端口占用: 确实是端口被占用,比如:没有正常关闭 Springboot 项目导致Springboot 项目换任何端口都提示端口占用,而且找不到占用端口的程序 2.环境 …

Qt中https的使用,报错TLS initialization failed和不能打开ssl.lib问题解决

前言 在现代应用程序中,安全地传输数据变得越来越重要。Qt提供了一套完整的网络API来支持HTTP和HTTPS通信。然而,在实际开发过程中,开发者可能会遇到SSL相关的错误,例如“TLS initialization failed”,cantt open ssl…

要注意!Google账号提示活动异常就要注意了,很可能下一步就是真•停用

很多朋友,在主动或被动登录谷歌账号时,被提醒账号活动异常,要验证手机号才能进一步使用谷歌账号,这是什么原因呢?如果不及时验证会出现什么状况呢,该如何解决这个问题呢?如果验证提示手机无法用…

一篇文章教你掌握——Pytorch深度学习实践基础

一篇文章教你掌握——Pytorch深度学习实践 1. Overview 概述1.1 Rule-based systems 基于规则的系统1.2 Classic machine learning 经典机器学习1.3 Representation learning 表征学习1.4 Brief history of neural networks 神经网络简史 2. 配置环境2.1 安装Anaconda2.2 创建虚…