单例模式之常见模式详解

单例模式之常见模式详解

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

单例模式的定义

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

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

单例模式的分类

在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(){
    }

}

单例模式的主要特点

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

单例模式的应用场景

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

总结

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

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

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

相关文章

MATLAB算法-数据挖掘算法详解,

Matlab是一种功能强大的数据分析和数据挖掘工具,提供了丰富的数据挖掘算法和函数。下面将介绍一些最著名的数据挖掘算法,并提供相应的代码示例。 K均值聚类算法(K-means Clustering): K均值聚类是一种常用的无监督学习算法,用于将数据集划分为K个不同的簇。以下是在Matla…

一些抄袭CSDN的爬虫网站(长期收集更新)

目录 一、CodeAntenna1. 简介2. 网址 二、待更新。。。 本文由CSDN点云侠原创,爬虫网站请努力加油爬。 一、CodeAntenna 1. 简介 互联网耻辱柱排行榜Top 1。本人博客里任何一点免费可读的部分都被该网站爬得体无完肤。 2. 网址 https://codeantenna.com/a/B4cMB…

【项目 进程3】2.6 exce函数族 2.7 进程退出、孤儿进程、僵尸进程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 2.6 exec函数族介绍(execute 执行)exec函数族 2.7 进程退出、孤儿进程、僵尸进程进程退出孤儿进程僵尸进程 2.6 exec函数族介绍(…

前端做excel的录入解析,将excel的数据传给后端,显示在页面上。

具体的流程如图所示: 1.点击excel录入按钮 2.打开弹框 3.点击上传按钮,会自动打开计算机本地文件,选择想上传的文件,点击打开 4.会将excel的数据解析成一个表格,可以在表格中做删除操作,点击确定 5.将exc…

Web3的2048,Sui 8192能否打开全链游戏的大门?

作者:Peng SUN,Foresight News Sui 8192:一局游戏就是一个NFT Sui 8192智能合约基于Move语言编写,构成非常简单,包括游戏、Game Board与排行榜(Leaderboard)三部分,覆盖方块移动、…

IOS与Android APP开发的差异性

iPhone和 Android是全球最流行的两种移动平台,有许多不同的开发者开发了应用程序,并将它们发布到市场上。虽然大多数开发者都使用了这两个平台,但您仍然需要了解它们的差异。 虽然 iOS和 Android两个平台都是基于 Linux,但它们却…

SOPC之NiosⅡ系统(五)

NIOS Ⅱ系统实例 目录 2.创建BSP工程 2.1 创建BSP工程 2.2 BSP Editor 2.3 创建C代码文件 3.Nios Ⅱ实例 3.1 Hello NIOS Ⅱ 3.2 System ID与Timestamp 3.3 蜂鸣器定时鸣叫 3.4 拨码开关输入GIO控制 4.FPGA器件的代码固化 4.1 嵌入式软件HEX文件生成 4.2 程序存储…

Linux进程控制(一)---进程创建和终止(写时拷贝,exit与_exit等)

目录 进程创建 fork()函数 子进程如何继承父进程的数据 1.创建时拷贝分离 2.写时拷贝★ 进程终止 进程终止时,操作系统做了什么? 进程终止的常见方式 代码运行完毕,结果正确 退出码★ 代码运行完毕,结果不正确 代码异…

自学网络安全(黑客)

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员(以编程为基础的学习)再开始学习 行为:从编程开始掌握,前端后端、通信协议、什么都学。 缺点:花费时间太长、实际向安全过渡后可用到的关键知识并不多。…

字体反爬破解

1、通过 f12 查看网页相关信息① 搜索“python”相关岗位,想爬取下来作为分析,但是看到html源码为特殊字符,而不是页面上直观能看到的文字信息②点击对应的css样式查看css源码,通过源码解析字体加密过程 2、通过 DomainURI 获取到…

北邮国院物联网 Microprocessor 微处理器笔记

Introduction-随便聊 嵌入式系统是什么?专用的计算机系统。为专门功能可能对计算机架构,外设等做出一些取舍。 通常的限制:Cost(比如大量部署传感器节点),Size and weight limits(特定应用场景…

【网关】ShenYu Gateway入门Demo体验,ShenYu网关2.6.0直接调用Dubbo服务

本次为新开源框架接入ShenYu网关做基础学习指导,特地来下载官网的demo体验一把,具体是想通过网关泛化调用dubbo服务。本次使用的是最新版本2.6.0。 官网文档: 如何通过 Apache ShenYu 网关代理 Dubbo 服务 | Apache Dubbo 环境准备 第一步&a…

git下载源码及环境搭建下载源码之后端(一)

学习目标: git下载源码 步骤: 下载源码 使用 windows R 使用cmd调用命令框下载gitee云上面的 源码文件 输入命令: Git clone (此处拼接gitee源代码 地址) 若使用 git 命令 clone 项目时 我们需要在系统变量中进行…

vue生命周期四个阶段(created和mount)

1.四个阶段 1)必经阶段 2)非必经阶段 提示:主动调用 vm.$destroy() 函数销毁后,可用 vm.$mount("#app") 将断开的 new Vue() 和页面重新建立虚拟 DOM 树,重新绑定起来挂载界面。 2. 生命周期钩子函数&…

【Unity 实用插件篇】| ReferenceFinder 引用查找插件,提高引擎查找使用效率

前言 【Unity 实用插件篇】| ReferenceFinder 引用查找插件,提高引擎查找使用效率一、ReferenceFinder 介绍二、使用示例三、实现方案3.1 方案选择3.2 查找及缓存3.3 界面实现 总结 前言 ReferenceFinder 是一个比较小众的插件,主要用来查找资源引用和…

【Java】Java实现微信小程序发送服务通知

文章目录 前言一、文档来源二、JAR包引入三、后端工作四、编写配置文件配置一:WxConfig配置二:WxProperties 五、代码编写 前言 在上个月接到一个需求,大概是需要计算一条数据的最大办理时间从而发送任务超期的微信小程序服务通知&#xff0…

IDDR和ODDR

IDDR D:输入双倍速率数据(IOB输入,且数据在时钟的上升沿和下降沿都会发生切换,即一个时钟周期发送2bit数据) CE:时钟使能信号(高有效) C:时钟信号 S,R&#x…

黑马大数据学习笔记2-HDFS基本操作

目录 进程启停管理一键启停脚本单进程启停 文件系统操作命令HDFS文件系统基本信息介绍创建文件夹查看指定目录下内容上传文件到HDFS指定目录查看HDFS文件内容下载HDFS文件拷贝HDFS文件追加数据到HDFS文件HDFS数据移动HDFS数据删除其他命令HDFS WEB浏览 HDFS权限修改权限 https:…

Spark MLlib快速入门(1)逻辑回归、Kmeans、决策树、Pipeline、交叉验证

Spark MLlib快速入门(1)逻辑回归、Kmeans、决策树案例 除了scikit-learn外,在spark中也提供了机器学习库,即Spark MLlib。 在Spark MLlib机器学习库提供两套算法实现的API:基于RDD API和基于DataFrame API。今天,主要介绍下Data…

FPGA实验四:交通灯控制器设计

目录 一、实验目的 二、设计要求 三、实验代码 1.design source文件代码 2.仿真文件代码 3.代码原理分析 四、实验结果及分析 1、引脚锁定 2、仿真波形及分析 3、下载测试结果及分析 五、实验心得 1.解决实验中遇见的问题及解决 2.实验完成的心得 一、实验目的 &a…