单例模式之常见模式详解

单例模式之常见模式详解

  • 单例模式的定义
  • 单例模式的分类
    • 饿汉模式
    • 懒汉模式
  • 单例模式的主要特点
  • 单例模式的应用场景
  • 总结

单例模式的定义

单例模式是一种设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来获取该实例。

在单例模式中,类的构造函数被私有化,这样其他类就无法直接创建该类的实例。而是通过一个静态方法或者属性来获取类的唯一实例。

单例模式的分类

在Java中实现单例模式的方法有很多,这里介绍最常见的两种

饿汉模式

以下是具体实现:


public class Singleton {//此处,先把实例创建出来private static  Singleton instance=new Singleton();//如果需要使用这个唯一实例,统一通过 Singleton.getInstance()方法来获取。public static Singleton getInstance(){return  instance;}//为了避免Singleton 类不小心被复制出多份来//把构造方法设置为private.在类外面,就无法通过new的方式来创建这个Singleton实例private Singleton(){}
}

在这里插入图片描述

此处static起着至关重要的作用:

  • static 保证这个实例唯一
  • static 保证这个实例确实在一定时机中被创建出来
    static 修饰使得当前 instance 属性是类属性,类属性是在类对象上的,类对象在一个java进程里是唯一的(只是在类加载阶段被创建出一个实例)

补充知识点
类加载:
java代码中的每个类都会在编译完成后得到 .class 文件。JVM运行时会加载这个 .class文件,读取其中的二进制指令,并且在内存中构造出对应的类对象。(形如Singleton.class)

在这里插入图片描述

  • 把构造方法设为private,在类外面,就无法通过new的方式来创建这个实例了。

饿汉模式的优点是实现简单、线程安全,因为实例在类加载时就已经创建好了。但缺点是如果该实例在整个程序运行期间没有被使用到,会造成资源浪费。

懒汉模式

以下是具体实现:

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

在这里插入图片描述

懒汉模式没有在类加载时进行初始化,而是在第一次使用该类的实例时,通过判断实例是否已经存在来决定是否创建实例。(延迟实例化,在需要时才创建唯一的实例。)

懒汉模式优点是实现简单,只有在需要时才创建实例,避免了资源浪费。但缺点是在多线程环境下可能会出现线程安全问题,需要额外处理。

如何让上述懒汉模式能够线程安全呢?进行加锁操作
在这里插入图片描述

由于使用了synchronized关键字,可能会影响性能。为了提高性能,可以使用双重检查锁定等方式进行优化。

上述代码会导致每次 getInstance() 操作都要加锁,加锁操作是有开销的,然而如果判断instance 的值是非空时,就会直接触发return操作,此时由于没有修改操作,就没必要加锁。

如下:
在这里插入图片描述

为了避免上述代码可能会遇到的内存可见性问题和指令重排序问题,使用volatile关键字进行优化。
代码如下:

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

单例模式的主要特点

  • 私有的构造函数:通过将构造函数设为私有,防止其他类直接创建实例。
  • 静态的实例变量:在类内部定义一个静态的实例变量,用于保存类的唯一实例。
  • 静态的获取方法:提供一个静态的方法或属性,用于获取类的唯一实例。这个方法会在第一次调用时创建实例,并在后续调用时返回同一个实例。

单例模式的应用场景

  • 系统中某个类的对象只需要存在一个实例,例如配置信息类、日志记录类等。
  • 需要频繁创建和销毁对象的场景,通过使用单例模式可以节省系统资源。
  • 对象需要被共享或者全局访问的场景,例如线程池、数据库连接池等。

总结

在实现单例模式时,需要注意线程安全性和延迟加载的问题。可以使用加锁、双重检查锁定等方式来确保线程安全,并且在需要时才创建实例,避免资源浪费。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国内什么牌子的ipad手写笔好用?电容笔性价比高推荐

随着平板电脑在校园、办公室中的应用越来越广泛,需要一种具有良好性能的电容笔。苹果品牌原装的这支电容笔,虽然功能很强,但因为其的价格实在是太贵了,所以只是用来学习记笔记,实在是太浪费了。所以,哪个电…

2023-07-12:RocketMQ如何做到消息不丢失?

2023-07-12:RocketMQ如何做到消息不丢失? 答案2023-07-12: RocketMQ通过刷盘机制、消息拉取机制和ACK机制等多种方式来确保消息投递的可靠性,防止消息丢失。 1.刷盘机制 RocketMQ中的消息分为内存消息和磁盘消息,内…

基于单片机智能洗衣机设计与实现

功能介绍 以51单片机作为主控系统;利用STC89C52单片机进行数据处理; 通过2路继电器分别控制洗衣机进水、出水相关逻辑运算;采用L298去掉直流电机实现滚筒正反转;通过单片机进行处理数据,把采集到的数据通过LCD液晶显示…

Ceph部署

目录 一、存储基础单机存储设备单机存储的问题 二、分布式存储(软件定义的存储 SDS)分布式存储的类型 三、Ceph 简介四、Ceph 优势五、Ceph 架构六、Ceph 核心组件七、OSD 存储后端八、Ceph 数据的存储过程九、Ceph 版本发行生命周期十、Ceph 集群部署基…

Linux环境下,通过Docker搭建及配置RabbitMQ

😊 作者: 一恍过去 💖 主页: https://blog.csdn.net/zhuocailing3390 🎊 社区: Java技术栈交流 🎉 主题: Linux环境下,通过Docker搭建及配置RabbitMQ ⏱️ 创作时间…

mac 如何批量修改图片名称

mac 如何批量修改图片名称?很多使用mac电脑的小伙伴一直有这样一个疑问,怎么在电脑上一次性的批量修改大量图片的名称,很多小伙伴在电脑上整理图片的时候都需要批量重命名,批量处理的功能可以让我们节省不少的时间和精力&#xff…

RocketMQ 5.1.0 在java中的使用

版本&#xff1a; 当前测试版本&#xff1a;springBoot 2.3.9、 RocketMQ 5.1.0 Maven或Gradle RocketMQ的依赖项&#xff1a; <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>5…

C# NPOI读取Excel中文乱码

Win11, 程序中需要从Excel表格读取中文内容&#xff0c;实测发现有中文乱码问题&#xff1a; class name:??Vege 奇怪的问号&#xff0c;原文是“蔬菜Vege”。 网上找了一圈&#xff0c;没找到NPOI中文乱码的解决方案&#xff0c;普遍都是比较顺利没遇到中文乱码问题。 那…

Web3.0:重新定义数字资产的所有权和交易方式

随着区块链技术的发展和应用&#xff0c;数字资产的概念已经逐渐深入人心。数字资产不仅包括加密货币&#xff0c;还包括数字艺术品、虚拟土地、游戏道具等各种形式的数字物品。然而&#xff0c;在传统的互联网环境下&#xff0c;数字资产的所有权和交易方式往往受到限制和约束…

一、机器学习前的数学基础知识

你说春天太短 还未来得及看见自己 就要粉碎成灯红酒绿的夏 那就开花呀 开他妈的 1. 求和、求积 1.1 求和 假设现在我们要在纸上写下1加到100的简单求和运算&#xff1a; 1 2 3 4 5 ........ 99 100 使用求和符号简化&#xff08;读作“西格玛”&#xff09;&#xff1a…

Linux进程控制【进程创建终止和等待】

文章目录 Linux进程控制【进程创建终止和等待】1. 进程创建1.1 fork函数1.2 写时拷贝 2. 进程终止2.1 进程退出码2.2 进程退出方法 3. 进程等待3.1 等待的必要性3.2 进程等待方法3.3 非阻塞等待 Linux进程控制【进程创建终止和等待】 创建进程之后&#xff0c;还需要对其进行管…

javascript截取两个符号之间的字符串(2):lastIndexOf匹配和正则表达式匹配

lastIndexOf匹配和正则表达式匹配 项目需求1.规范的字符串2.不规范的字符串3-1.万能封装3-2.ChatGPT的优化写法4.正则表达式的用法5.补充知识&#xff1a;lastIndexOf的用法 项目需求 javascript中截取字符串中最后一个“/”和“?”之间的内容。 1.规范的字符串 https://tes…