java设计模式——单例模式(Singleton Pattern)

java设计模式之单例模式——Singleton pattern 设计模式故事会:https://blog.youkuaiyun.com/weixin_40205234/article/details/90664824 单例模式 单例模式(Singleton pattern)是java中最常见的设计模式之一。该模式属于创建型设计模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一... 阅读详情
定义:
        单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。 单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。

要点:
  1. 某个类只能有一个实例;
  2. 它必须自行创建这个实例;
  3. 它必须自行向整个系统提供这个实例。

单例模式在开发中经常会被用到,写法也多种多样,下面分析几种单例模式的写法:

单线程:
public class Singleton {
    private static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        if (null == instance){
            instance = new Singleton();
        }
        return instance;
    }
}

上面这种写法是线程不安全的,适用于单线程,因为当有两个线程的时候,假如A线程执行if条件语句时,B线程也有可能执行该语句,所以不能用于多线程。为了能够适用于多线程,可以加一道锁。

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

加了同步锁之后就可以在多线程中正常执行了,但是如果单例的方法被多个线程频繁的访问,这样就导致程序执行性能下降,那有没有更好的写法呢?前辈们的智慧是伟大的,他们想出了一个更好的方案——双重检查锁定。通过双重效验来降低同步开销。

public class Singleton {
    private static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        if (null == instance){                     //第一次检查
           synchronized (Singleton.class){       //加同步锁
               if (null == instance){             //第二次检查
                   instance = new Singleton();   //创建对象
                }
            }
        }
        return instance;
    }
}

如上面代码所示,如果第一次检查instance不为null,那么就不需要执行下面的加锁和初始化操作。因此,可以大幅降低synchronized带来的性能开销。 双重检查锁定看起来似乎很完美,但这是一个错误的优化!为什么呢?在线程执行到第4行,代码读取到instance不为null时, instance引用的对象有可能还没有完成初始化。
在第8行创建了一个对象,这行代码可以分解为如下的3行伪代码:

memory = allocate();     // 1.分配对象的内存空间
initinstance(memory);    // 2.初始化对象
instance = memory;       // 3.设置instance指向刚才分配的内存地址

上面3行代码中的2和3之间,可能会被重排序(在一些JIT编译器上,这种重排序是真实发生的,如果不了解重排序,后文JMM会详细解释)。 2和3之间重排序之后的执行时序如下:

memory = allocate();     // 1.分配对象的内存空间
instance = memory;       // 3.设置instance指向刚才分配的内存地址
initinstance(memory);    // 2.初始化对象

如果出现重排序的情况会造成什么后果?假如A线程执行到创建对象的时,然后初始化对象的过程是按照上述顺序初始化,当执行到第二行(instance = memory)时,线程B在第一次检查的时候判断是不为空的,那么接下来如果线程B使用这个对象时就会出现空指针的情况。所以为了避免这个问题,有两种解决方法:
  • 不允许重排序的情况。
  • 不允许其他线程“看到”这个重排序。
具体解决方案一(静态内部类):

public class Singleton {
    private Singleton(){}
    private static class SingletonHolder{
        private static Singleton instance = new Singleton();
    }
    public static Singleton getInstance(){
        return SingletonHolder.instance;     //这里才会导致 SingletonHolder类被初始化
    }
}

这个方案的本质是允许前面伪代码谈到的2和3重排序,但不允许其他线程“看到”这个重排序。在Singleton 示例代码中, 首次执行getInstance()方法的线程将导致InstanceHolder类被初始化。由于Java语言是多线程的, 多个线程可能在同一时间尝试去初始化同一个类或接口(比如这里多个线程可能会在同一时刻调用getInstance()方法来初始化IInstanceHolder类)。 Java语言规定,对于每一个类和接口C,都有一个唯一的初始化锁LC与之对应。从C到LC的映射,由JVM的具体实现去自由实现。 JVM在类初始化期间会获取这个初始化锁,并且每个线程至少获取一次锁来确保这个类已经被初始化过了。

方案二(volatitle):

public class Singleton {
    private volatile static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        if (null == instance){                     //第一次检查
           synchronized (Singleton.class){       //加同步锁
               if (null == instance){             //第二次检查
                   instance = new Singleton();   //创建对象
                }
            }
        }
        return instance;
    }
}

当声明对象的引用为volatile后,前面伪代码谈到的2和3之间的重排序,在多线程环境中将会被禁止。

在单例模式的实现过程中,需要注意如下三点:
  • 单例类的构造函数为私有;
  • 提供一个自身的静态私有成员变量;
  • 提供一个公有的静态工厂方法。

单例模式优点:
  • 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
  • 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。
  • 允许可变数目的实例。我们可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例。

单例模式缺点:
  • 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
  • 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。
  • 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收的技术, 因此,如果实例化的对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致对象状态的丢失。

单例模式适用环境:
  • 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器,或者需要考虑资源消耗太大而只允许创建一个对象。
  • 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。
  • 在一个系统中要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就需要对单例模式进行改进,使之成为多例模式





















【Java设计模式】Java设计模式之(一)单例模式(Singleton Pattern) 本文继续介绍23种设计模式详解系列之单例模式。 一、单例模式的定义 指一个类只有一个实例,且该类能自行创建这个实例的一种模式。 二、单例模式的常见例子 Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误;在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中 阅读详情

相关推荐

从Peer到脉冲地震波:免费Python工具全流程配置教程(PyCharm+Anaconda)

本文详细介绍了如何使用Python工具链(PyCharm+Anaconda)实现从Peer数据库获取地震波数据到生成脉冲地震波的全流程配置。通过开源工具EQTOOL和PySeismicGen,结合Python环境搭建、数据格式转换和脉冲地震动生成技术,为结构抗震分析提供高效、灵活的解决方案。

weixin_29093169的博客 430

java 双重检查单例和静态内部类单例

最近在看imageLoader 源码的时候,看到单例采用的双重检查机制,但是在看其他大牛写的代码的时候,采用的是静态的内部类作为单例,在此研究下。下面是单例的相关内容: 懒汉式 //懒汉式单例类.在第一次调用的时候实例化自己 public class Singleton { private Singleton() {} private static Singleton

android_小路的博客 5327

使用MKL+Eigen求解稀疏矩阵方程组

问题:求解Ax=b的解,其中,A为大型稀疏矩阵,长和宽分别为1500^2。 一般思路: (1)A为对称正定矩阵,对A使用cholesky分解。 (2)A为对称不定矩阵,使用LDL‘分解,即: PAP'=LDL' 其中,L为单位下三角矩阵,D由阶数为1或者2的对角块构成,P是置换矩阵。 (3)不对称矩阵:LU分解。 (4)长方形矩阵(长...

薛晓伟 3445

Java设计模式—单例模式(Singleton Pattern)

Java设计模式—单例模式(Singleton Pattern)

白白白鲤鱼的博客 3305

操作系统知识点汇总(王道)

操作系统不论是就业还是升学都是核心的一门课程,对于大部分工科更是必修课程。本文章是对《王道操作系统》所有知识点的总结笔记,以供大家学习以及在备考期间复习使用。让我们一起把知识往脑子里旋好吗!!!......

S mile0804的博客 5万+

什么!!!寒假就要准备暑期实习

介绍暑期实习,从作用,时间线,投递渠道,技术准备,常见问题,经验教训几个方面介绍暑期实习

今天不coding的博客 1724

详解Java设计模式之单例模式(Singleton Pattern)

单例模式只包含一个 Singleton(单例角色)类,在单例类的内部实现只生成一个实例,同时它提供一个静态的getInstance()工厂方法,让客户可以使用它的唯一实例。

Elegance never goes out of fashion 2745

深度学习Halcon中GPU显存利用率高,但GPU、CPU利用率较低,导致模型训练速度很慢,通过设置硬件参数的解决方法

深度学习Halcon中GPU显存利用率高,但GPU、CPU利用率较低,导致模型训练速度很慢,通过设置硬件参数的解决方法 前言 在训练自己模型的时候,会遇到GPU显存利用率高,但GPU、CPU利用率较低,导致模型训练速度很慢的问题。这个问题一方面是由于硬件没有设置到最佳工作状态,另一方面是代码中参数没有设置好。最近在跑Halcon DL遇到这个问题,而Halcon不像开源的几个框架那样自由,代码封装的比较多。所以遇到这种问题,只能在参数最优的情况下,通过设置硬件参数来提升性能。 当然,在跑DL之前,无论什么框

ZiLiangQin的博客 9914

java设计模式(Design Pattern) — 单例模式(Singleton Pattern)

本文参考ImportNew中的文章:http://www.importnew.com/6662.html 单例模式是java中常使用的一种设计模式,通过阻止外部实例化来修改,来控制所建对象的数量。 单例模式的特点: 1. 构造函数私有化; 2. 建立自己私有化的实例; 3. 创建公共静态方法,为外界提供调用单一实例的接口。 下面看一个单例模式的例子: Singleton Class:

zhenzi_1989的专栏 882

实战:RK3568 Android14 集成 AP6212A WiFi/BT 二合一模块

AP6212A 的集成在 RK3568 上非常成熟。只要电源、32K 时钟、SDIO 线序、UART 流控这四点硬件没问题,软件上主要是 DTS 对应的 GPIO 别填错即可。希望这篇博文能帮你一次点亮 WiFi 和蓝牙!

qq_33427070的博客 1446

基于改进YOLOv5的小目标检测 | 添加CBAM注意机制 + 更换Neck网络之BiFPN + 增加高分辨率检测头

本文针对图像中小目标难以检测的问题,提出了一种基于YOLOv5的改进模型。在主干网络中,加入CBAM注意力模块增强网络特征提取能力;在颈部网络部分,使用BiFPN结构替换PANet结构,强化底层特征利用;在检测头部分,增加高分辨率检测头,改善对于微小目标的检测能力。本文算法在无人机数据集VisDrone2019数据集上进行了多次对比实验,结果表明本文算法可以有效地检测小目标。🌈

小哥谈 2934

Java 设计模式 二 单例模式 (Singleton Pattern)

单例模式是一种非常常见且有用的设计模式,能够确保类只有一个实例,并且提供全局访问点。在 Java 中,推荐使用静态内部类单例模式和枚举单例模式,这两种方式在性能、线程安全性和代码简洁性上都非常优秀。

空 1307

AUTOSAR进阶图解==>AUTOSAR_SWS_CANNetworkManagement

本文介绍了AUTOSAR架构中的CAN网络管理(CanNm)模块,主要内容包括: 模块概述:CanNm是协调CAN网络节点状态转换的基础组件,采用去中心化设计,通过周期性发送网络管理PDU保持网络活跃状态,支持网络唤醒、睡眠和部分网络功能。 架构设计:CanNm位于AUTOSAR中间层,连接上层通信管理器(ComM)和底层CAN接口(CanIf),包含状态管理、PDU处理和定时器管理等子组件。 状态机设计:定义了三种主要模式(总线睡眠、准备睡眠和网络模式)及其转换逻辑,网络模式又包含重复消息、正常操作和准备

一名留德华的,康德的信徒的,专注于汽车电子领域的博客 2037

【设计模式】Java 设计模式之单例模式(Singleton Pattern)

单例模式是一种确保类只有一个实例并提供全局访问点的设计模式。它适用于需要频繁实例化但只需一个实例的场景,如配置信息类或数据库连接池。实现方式有饿汉式和懒汉式,需注意线程安全性和防止反序列化问题。尽管单例模式实用,但滥用可能导致代码结构复杂和测试困难。在Spring框架中,单例是默认bean作用域,但应根据实际业务需求决定是否使用。灵活运用设计模式,结合具体场景和技术栈,是提高设计能力和代码质量的关键。在应用单例模式时,需权衡其优缺点,并避免潜在问题。

新手村长的专栏 1512

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java23种设计模式 单例模式【Singleton Pattern】

本文章转载大佬CBF4LIFE的文章 博客地址:https://www.cnblogs.com/cbf4life/ 这个模式是很有意思,而且比较简单,但是我还是要说因为它使用的是如此的广泛,如此的有人缘, 单例就是单一、独苗的意思,那什么是独一份呢?你的思维是独一份,除此之外还有什么不能山寨的呢? 我们举个比较难复制的对象:皇帝  中国的历史上很少出现两个皇帝并存的时期,是有,但不多,那我们就认...

宇智波带土 217

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Java设计模式-单例模式详解(Singleton Pattern)

一、单例设计模式概述1、单例模式简介单例模式(Singleton Pattern)是Java中最常见最简单的设计模式之一。这种设计模式属于五个创建型的一种,他提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象方式,可以直接访问,不需要也不能直接从该类外部进行实例化,即在该类的外部不能直接使用new关键字进行...

超级字节码的博客 694

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Java常用设计模式-单例模式(Singleton Pattern)

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式 特点: 单例类只能有一个实例。 单例类必须自己创建自己的唯一实例。 单例类必须给所有其他对象提供这一实例 懒汉式: package com.example; /** * 懒汉式 * 加锁 synchronized线程安全 */ public class Stu...

gang_luo的博客 433

JAVA23种设计模式之单例模式(Singleton Pattern)

单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。 注意 单例类只能有一个实例。 单例类必须自己创建自己的唯一实例。 单例类必须给所有其他对象提供这一实例。 介绍 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。 主要解决:一个

fuu123f的博客 221

Java设计模式--单例模式【Singleton Pattern】

在宇宙中,太阳是唯一的,独一份的,不可复制的,人们每天抬头看到的太阳都是同一个,不会随着斗转星移就多产生一个太阳,所以太阳就是绝对的单例。下面就以“太阳”为例介绍单例模式。      所谓单例模式就是保证一个类有且只有一个实例。要创建一个独一无二的对象实例,就必须保证程序其他地方不能创建出该单例对象的新实例。     设计一个单例类时,需要确定何时初始化该类的单例对象。     1、第一

CoderLover 428

重走Java设计模式-单例模式(Singleton Pattern)

我们在开发当中使用最多的就是单例模式,那么什么是单例模式,下面我给大家分享我理解的单例模式。

pingguocu3的博客 696

【Java】设计模式之单例模式(Singleton Pattern)

 单例模式是 Java 众多设计模式的一种,也是平时用到较多、适用范围较广的一种设计模式,隶属创建型模式。 什么设计模式?说白了就是问题的解决方案,计算1加到100可以每个数字逐个加,也可以像高斯一样首尾相加乘50,设计模式是对问题的一种优秀的解决方案,所以我们需要来看看单例模式这个答案出现之前,所存在的问题: 假设有一个类 它的对象需要被频繁的使用,所以经常需要创建与销毁,而恰...

Decmoon的博客 348

java设计模式:单例模式【Singleton Pattern】

 单例模式很简单,就是在构造函数中多了加一个构造函数,访问权限是 private 的就可以了,这个模式是简单,但是简单中透着风险,风险?什么风险?在一个 B/S 项目中,每个 HTTPRequest 请求到 J2EE的容器上后都创建了一个线程,每个线程都要创建同一个单例对象。 /** * I'm glad to share my knowledge with you all. * 中国

Lee_my_的专栏 887

java23种设计模式之一: 单例模式(Singleton Pattern)

单例模式(Singleton Pattern)是设计模式中比较常用的一种,下面来总结单例模式的知识,包括: 1、理解什么是单例模式、单例模式有什么优点/缺点、单例模式的应用场景; 2、再来看看Java单例模式的6种代码实现方式、每种实现方式有什么需要注意的; 3、后面再来了解Java单例模式其他值得关注的地方,如比较静态方法、以及Java反...

255

Java设计模式——单例模式(Singleton Pattern)

从上一篇文章Java设计模式——装饰模式(Decorator Pattern)中估计大家都已经对java设计模式有了初步的理解,今天呢,阿Q就给大家讲一下另一种设计模式——单例设计模式。首先我们先来了解一下它的概念,单例模式是设计模式中最简单的形式之一,这一模式的目的是使得类的一个对象成为系统中的唯一实例,也就是保证类在内存中只有一个对象。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一...

阿Q的小窝 405

java设计模式之单例模式(Singleton Pattern)

本文中介绍了几种实现单例的方法,主要包括饿汉、懒汉、使用静态内部类、双重校验锁、枚举等。还介绍了如何防止序列化破坏类的单例性。从单例的实现中,我们可以发现,一个简单的单例模式就能涉及到这么多知识。在不断完善的过程中可以了解并运用到更多的知识。所谓学无止境。

白话机器学习 261
上一篇: java设计模式——抽象工厂模式(Abstract Factory Pattern)
下一篇: java设计模式——建造者模式(Builder Pattern)
OODeveloper
博客等级 码龄12年 43粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值