2.单例模式

news2024/12/25 1:38:53

基本概念

单例模式:保证一个类只有一个实例,并提供一个访问该实例的全局访问点

常见应用场景

  • 读取配置文件的类一般设计为单例模式
  • 网站计数器
  • 应用程序的日志应用,因为共享日志文件一直处于打开状态,只能有一个实例去操作
  • Spring 中初始化 bean 默认为单例
  • Servlet 编程中,每个 servlet 都是单例
  • Spring MVC / Struts1 框架,控制器对象是单例

单例模式优点

(1) 由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如:读取配置、产生其他依赖对象时,可以通过在应用启动时直接产生一个单例对象,然后以永久驻留内存的方式解决

(2) 单例模式可以在系统设置全局变量访问点,优化了共享资源的访问

常见单例实现方式

1. 饿汉式(静态常量)

优点:写法简单,在类加载时就完成了实例化;避免了线程同步问题

缺点:没有达到懒加载的效果,如果没有用到这个实例,将造成内存浪费

结论:可用于实际开发

public class Singleton {
    /**
     * 1.构造器私有化
     */
    private Singleton() {}
	
    /**
     * 2.类内部创建对象实例
     */
    private final static Singleton INSTANCE = new Singleton();
	
    /**
     * 3.提供公有静态方法,返回实例对象
     */
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

2. 饿汉式(静态代码块)

该方式和静态常量的方式类似,只不过将类实例化的过程放在了静态代码块中;即在类装载的时候,就执行静态代码块中的代码,初始化类的实例;优缺点和静态常量的方式一样

结论:可用于实际开发

public class Singleton {
    /**
     * 1.构造器私有化
     */
    private Singleton() {}
	
    /**
     * 2.类内部创建对象属性
     */
    private static Singleton INSTANCE;
	
    /**
     * 3.在静态代码块中创建单例对象
     */
    static {
        INSTANCE = new Singleton();
    }
	
    /**
     * 4.提供公有静态方法,返回实例对象
     */
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

3. 懒汉式(线程不安全)

优点:起到了懒加载的效果,但只能在单线程的场景下使用

缺点:如果在多线程下,一个线程还在 if 判断语句块,而另一个线程通过了 if 代码块,就会产生多个实例

结论:实际开发中,不推荐使用该方式

public class Singleton {
    /**
     * 1.构造器私有化
     */
    private Singleton() {}
	
    /**
     * 2.类内部创建对象属性
     */
    private static Singleton INSTANCE;
	
    /**
     * 3.提供公有静态方法,返回实例对象
     */
    public static Singleton getInstance() {
        return null == INSTANCE ? new Singleton() : INSTANCE;
    }
}

4. 懒汉式(线程安全,同步方法)

对方式 3 进行改进,对返回单例对象的 getInstance() 方法添加 synchronized,保证线程安全;即多个线程不能同时调用 getInstance() 方法

优点:解决了线程不安全的问题

缺点:效率太低,多个线程想获取类的实例的时候,执行 getInstance() 方法都要同步;而其实该方法只执行一次实例化代码就够了,其他的线程想获取该类的实例,直接 return 就行了;使用方法同步降低了效率

结论:实际开发中,不推荐使用该方式
public class Singleton {
/**
* 1.构造器私有化
*/
private Singleton() {}

/**
 * 2.类内部创建对象属性
 */
private static Singleton INSTANCE;

/**
 * 3.提供公有静态方法,返回实例对象
 */
public static synchronized Singleton getInstance() {
    return null == INSTANCE ? new Singleton() : INSTANCE;
}

}

5. 双重检查

加入了双重检查代码,解决了线程安全的问题,同时也解决了懒加载的问题,效率较高

结论:可用于实际开发

public class Singleton {
    /**
     * 1.构造器私有化
     */
    private Singleton() {}
	
    /**
     * 2.类内部创建对象属性
     */
    private static volatile Singleton INSTANCE;
	
    /**
     * 3.提供公有静态方法,返回实例对象
     */
    public static Singleton getInstance() {
        if(null == INSTANCE) {
            // 保证创建实例对象的时候, 只能有一个线程
            synchronized(Singleton.class) {
                if(null == INSTANCE) {
                    INSTANCE = new Singleton();
                }
            }
        }
        return INSTANCE;
    }
}

6. 静态内部类(推荐)

当外部类 Singleton 装载的时候,内部类 SingletonInstance 并不会立即装载,实现了延迟加载

只有在调用 getInstance() 方法的时候,才使用到内部类,这时候内部类才会装载;而类的装载过程是线程安全的,即保证了线程安全

所以静态内部类这种方式既保证了懒加载,又保证了线程安全

结论:强烈推荐

public class Singleton {
    /**
     * 1.构造器私有化
     */
    private Singleton() {}
	
    /**
     * 2.通过静态内部类实例化对象
     */
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }
	
    /**
     * 3.提供公有静态方法,返回实例对象
     */
    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

7. 枚举(推荐)

借助 JDK1.5 添加的枚举实现单例模式,不仅避免了多线程同步的问题,还能防止反序列化重新创建新的对象

结论:强烈推荐

public enum Singleton {
    /**
     * 定义单例对象属性
     */
    INSTANCE;
	
    /**
     * 定义单例对象方法
     */
    public void method() {
        System.out.println("枚举实现单例");
    }
}

不同实现方式效率对比
在这里插入图片描述

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

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

相关文章

新C++(11):unordered_map\set的封装

"假如可以让音乐停下来"一、unordered_map\unordered_set简介在C98中,STL底层提供了以红黑树封装的关联式容器map\set,其查询效率可以达到LogN(以2为底)。而在C11中,STL又提供了unordered(无序)容器,其使用方式与map\se…

企业对不同形态CRM系统价格需求不同

很多企业在选型时关心CRM客户管理系统的价格,有人对CRM的价格完全没有概念,也有的人先问价格再看其他。CRM价格在系统选型中到底有多重要?不同类型CRM系统的价格是否有所不同? CRM的不同产品形态也会影响价格 通常情况下&#x…

十五、MyBatis使用PageHelper

1.limit分页 limit分页原理 mysql的limit后面两个数字: 第一个数字:startIndex(起始下标。下标从0开始。) 第二个数字:pageSize(每页显示的记录条数) 假设已知页码pageNum,还有每页…

移动端笔记

目录 一、移动端基础 二、视口 三、二倍图/多倍图 四、移动端开发 (一)开发选择 (二)常见布局 (三)移动端技术解决方案 五、移动WEB开发之flex布局 六、移动WEB开发之rem适配布局 #END&#xff08…

嘀嗒出行再闯IPO:千军万马我无懈

羽扇纶巾笑谈间,千军万马我无懈。 在激烈竞争中再度冲刺港交所IPO的嘀嗒出行,闪露出一丝歌词里的气魄。交通运输部下属网约车监管信息交互系统的数据显示,截至2023年1月31日,全国共有300家网约车平台公司取得网约车平台经营许可。…

如何使用COM-Hunter检测持久化COM劫持漏洞

关于COM-Hunter COM- Hunter是一款针对持久化COM劫持漏洞的安全检测工具,该工具基于C#语言开发,可以帮助广大研究人员通过持久化COM劫持技术来检测目标应用程序的安全性。 关于COM劫持 微软在Windows 3.11中引入了(Component Object Model, COM)&…

2月第4周榜单丨飞瓜数据B站UP主排行榜(哔哩哔哩平台)发布!

飞瓜轻数发布2023年2月20日-2月26日飞瓜数据UP主排行榜(B站平台),通过充电数、涨粉数、成长指数三个维度来体现UP主账号成长的情况,为用户提供B站号综合价值的数据参考,根据UP主成长情况用户能够快速找到运营能力强的B…

基频估计算法简介

基频估计算法 F0 estimate methods 估计F0的方法可以分为三类:基于时域、基于频域、或混合方法。本文详细介绍了这些方法。 所有的算法都包含如下三个主要步骤: 1.预处理:滤波,加窗分帧等 2.搜寻:可能的基频值F0(候选…

chatgpt到底颠覆了什么 第二部分

以第二个理由就是两个字,垄断。 现在谈到范式转变,如果首先谈的还是算法,那说明还没有透彻理解范式改变范式改变,首先要改的是什么。是什么?是参赛资格。 过去我相信大企业大团队聚拢了许多聪明的脑袋,但我…

基于神经网络补偿的主动悬架自适应控制

目录 前言 1. 1/4悬架模型 2.仿真分析 2.1仿真模型 2.2仿真结果 2.1 形① 2.2 形② 3. 总结 前言 上两篇博客我们介绍了神经网络补偿控制律的仿真测试,从仿真结果我们可以得知神经网络具有逼近扰动,并将其补偿的作用。 上两篇文章链接&#xf…

在nestjs中进行typeorm cli迁移(migration)的配置

在nestjs中进行typeorm cli迁移(migration)的配置 在学习nestjs过程中发现typeorm的迁移配置十分麻烦,似乎许多方法都是旧版本的配置,无法直接使用. 花了挺长时间总算解决了这个配置问题. db.config.ts 先创建db.config.ts, 该文件export了两个对象,其…

AcWing算法提高课-3.1.2信使

宣传一下算法提高课整理 <— CSDN个人主页&#xff1a;更好的阅读体验 <— 题目传送门点这里 题目描述 战争时期&#xff0c;前线有 nnn 个哨所&#xff0c;每个哨所可能会与其他若干个哨所之间有通信联系。 信使负责在哨所之间传递信息&#xff0c;当然&#xff0c;…

CPU 偏高,和linux常用命令

CPU 偏高&#xff0c;和linux常用命令一、1、常用命令2、top 查看整体的cpu占有率&#xff08;哪个进程cpu占用过高&#xff09;3、top -Hp 8779 查看该pid 下哪个进程占用过高4、打印dump日志 重点关注&#xff08;RUNNABLE、BLOCKED&#xff09;一、 1、常用命令 整机 top …

k8s ConfigMap 中 subPath 字段和 items 字段

Kubernetes中什么是subPath 有时&#xff0c;在单个 Pod 中共享卷以供多方使用是很有用的。volumeMounts.subPath 属性可用于指定所引用的卷内的子路径&#xff0c;而不是其根路径。 这句话理解了&#xff0c;基本就懂subPath怎么用了&#xff0c;比如我们要替换nginx.cnf, 挂…

map和set的使用

文章目录关联式容器树形结构的关联式容器setinsert增减erase删除multiset修改mappair<key,value>insertoperator[] 的引入insert和operator[]的区别multimap小结map的使用统计最喜欢吃的前几种水果前K个高频单词&#xff0c;返回单词的频率由高到低,频率相同时&#xff0…

Isaac-gym(9):项目更新、benchmarks框架梳理

一、项目更新 近期重新git clone isaac gym的强化部分&#xff08;具体见系列第5篇&#xff09;时发现官方的github库有跟新&#xff0c;git clone下来后发现多了若干个task&#xff0c;在环境配置上也有一定区别。 例如新旧两版工程项目的setup.py区别如下&#xff1a; git …

现在的00后太强了,几个问题差点给我问懵了

前言 我们公司刚入职一个00后小伙&#xff0c;今天在办公室交流了一下&#xff0c;他问我会不会自动化测试&#xff0c;我说懂一点&#xff0c;然后直接问了我几个自动化测试问题&#xff0c;差点直接给我问懵了&#xff01; 问题如下&#xff1a; 我们在制定自动化测试实施…

计算机组成原理4小时速成5:输入输出系统,io设备与cpu的链接方式,控制方式,io设备,io接口,并行串行总线

计算机组成原理4小时速成5&#xff1a;输入输出系统&#xff0c;io设备与cpu的链接方式&#xff0c;控制方式&#xff0c;io设备&#xff0c;io接口&#xff0c;并行串行总线 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c…

刷题笔记1 | 704. 二分查找,27. 移除元素

704. 二分查找 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 输入: nums [-1,0,3,5,9,12], target 9 输出: 4 …

备战蓝桥杯——sort函数

备战蓝桥杯——sort函数排列字母lambda匿名函数排列字母 链接: 排列字母 不用多说&#xff0c;很简单的签到题&#xff0c;我们先来了解一下sort函数的用法 list.sort(cmpNone, keyNone, reverseFalse) cmp:进行比较的方法&#xff08;可以自定义排序的方法&#xff0c;通常…