单例模式八大方式详解

【理论知识】单例模式(懒汉式+饿汉式+枚举) 软件设计模式(Software Design Pattern) 又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。其目的是为了提高代码的可重用性、代码的可读性和代码的可靠性。... 阅读详情

单例模式

模式介绍

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。

比如 Hibernate 中的 SessionFactory ,它充当数据存储源的代理,并负责创建 Session 对象。 SessionFactory 并不是轻量级的,一般情况下,一个项目通常只需要一个 SessionFactory 就够,这是就会使用到单例模式。

八种方式

  1. 饿汉式(静态常量)
  2. 饿汉式(静态代码块)
  3. 懒汉式(线程不安全)
  4. 懒汉式(线程安全,同步方法)
  5. 懒汉式(线程安全,同步代码块)
  6. 双重检查
  7. 静态内部类
  8. 枚举
饿汉式(静态常量)

饿汉式就是不管外界是否需要使用到这个单例,在类本身初始化的时候就已经将实例创建了。

步骤如下
  1. 创建实例属性
  2. 构造器私有化(避免外界访问)
  3. 类的内部创建对象
  4. 向外暴露一个静态的公共方法获取实例
实例演示
public class SingleTon01 {
    // 构造器私有化,禁止外界访问
    private SingleTon01(){}

    // 创建单一实例
    private static final SingleTon01 instance = new SingleTon01();

    // 向外界提供获取唯一实例的方法
    public static SingleTon01 getSingleTon01(){
        return instance;
    }
}
优缺点

优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。

没有线程同步的问题,是因为不会因为线程调用方法时多次创建实例对象,唯一的实例对象在类初始化时已经创建完毕。

缺点:在类装载的时候就完成实例化,没有达到懒加载(需要才创建,懒惰式)的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。

饿汉式(静态代码块)

通过静态代码块的形式创建单例对象。

演示
static {
    instance = new SingleTon01();
}
优缺点

这种方式和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块中,也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点和上面是一样的。

结论:这种单例模式可用,但是可能造成内存浪费

懒汉式(线程不安全)

懒汉即需要才创建,不会主动提前创建。

演示
public class SingleTon02 {
    private static SingleTon02 single02;

    private SingleTon02(){}

    public SingleTon02 getSingle02(){
        if (single02 == null) {
            single02 = new SingleTon02();
        }
        
        return single02;
    }
}
优缺点
  1. 起到了懒加载的效果,但是只能在单线程下使用。

  2. 如果在多线程下,一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式

    多线程并发问题,并发进入,导致多个实例创建

结论:在实际开发中,不要使用这种方式。

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

在实例获取方法上添加同步锁。

演示
public class SingleTon03 {
    private static SingleTon03 single03;

    private SingleTon03(){}

    public synchronized SingleTon03 getSingle03(){
        if (single03 == null)
            single03 = new SingleTon03();
        return single03;
    }
}
优缺点
  1. 解决了部分线程不安全问题,并不是完全的线程安全

  2. 效率太低了,每个线程在想获得类的实例时候,执行getSingle03()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了。方法进行同步效率太低。

    锁的范围太大,影响多线程执行效率

结论:在实际开发中,不推荐使用这种方式。

懒汉式(线程不安全,同步代码块)

通过将synchronized关键字的范围缩小,同步部分代码,提高多线程并发执行下的效率。

演示
public class SingleTon04 {
    private static SingleTon04 singleTon04;
    
    private SingleTon04(){}
    
    public static SingleTon04 getSingleTon04(){
        if (singleTon04 == null){
            synchronized (SingleTon04.class){
                singleTon04 = new SingleTon04();
            }
        }
        return singleTon04;
    }
}
优缺点
  1. 这种方式,本意是想对第四种实现方式的改进,因为前面同步方法效率太低,改为同步产生实例化的的代码块

  2. 但是这种同步并不能起到线程同步的作用。跟第3种实现方式遇到的情形一致,假如一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。

    这个同步代码块锁的是整个类,在没执行这个方法前,已经有多个线程进入到这个类中,那么锁就无法对已经进入的线程起到作用。(可重入锁)

结论:在实际开发中,不能使用这种方式

改进

双端检锁加volatile修饰,单双端检锁也是线程不安全的,涉及到对象内存的分配问题。

public class SingleTon04 {
    // 在变量上添加volatile是增加变量的可见性
    private volatile static SingleTon04 singleTon04;

    private SingleTon04(){}

    // 双端检锁为了防止在执行该方法前已经进入该类的线程
    public static SingleTon04 getSingleTon04(){
        if (singleTon04 == null){
            synchronized (SingleTon04.class){
                if (singleTon04 == null)
                singleTon04 = new SingleTon04();
            }
        }
        return singleTon04;
    }
}
优缺点
  1. Double-Check概念是多线程开发中常使用到的,如代码中所示,我们进行了两次if (singleton == null)检查,这样就可以保证部分线程安全了。
  2. 这样,实例化代码只用执行一次,后面再次访问时,判断if (singleton == null),直接return实例化对象,也避免的反复进行方法同步.
  3. 线程安全、延迟加载、效率较高

结论:在实际开发中,推荐使用这种单例设计模式

静态内部类

通过内部类的机制来进行单例的创建。

演示
public class Singleton05 {
    private static class getInstance {
        private static final Singleton05 singleton05 = new Singleton05();
    }

    private Singleton05(){}

    public static Singleton05 getSingleTon05(){
        // 直接调用内部类的属性
        return getInstance.singleton05;
    }
}
优缺点
  1. 这种方式采用了类装载的机制来保证初始化实例时只有一个线程。
  2. 静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getSingleTon05方法,才会装载getInstance内部类,从而完成Singleton的实例化。
  3. 类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。

优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高

结论:推荐使用

枚举

枚举本身就是一个类,是一种语法糖。本身枚举的构造器是私有的。

演示
enum SingleTon06 {
    // instance就是SingleTon06唯一的实例
    INSTANCE;
    public void method(){}
}
优缺点
  1. 这借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而
    且还能防止反序列化重新创建新的对象。
  2. 这种方式是Effective Java作者Josh Bloch 提倡的方式

结论:推荐使用

单例模式在JDK 应用的源码分析

java.lang.Runtime就是经典的单例模式(饿汉式),这里可以使用饿汉式是因为,在多线程下这个类是一定会用到的,这样也可以保证线程安全。

下面是部分源码

public class Runtime {
    private static Runtime currentRuntime = new Runtime();


    public static Runtime getRuntime() {
        return currentRuntime;
    }
}

单例模式注意事项和细节说明

  1. 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
  2. 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new来创建实例对象
单例模式使用的场景

需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)

设计模式之单例模式(七种方法超详细) 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象,也就是说不能使用new关键字来创建对象。 阅读详情

相关推荐

单例模式介绍

目录 1 前言 2 单例模式类型 2.1 饿汉式: 2.2 懒汉式: 2.2.1 双重检查锁 2.2.2volatile防止指令重排 2.3 静态内部类 3 破坏单例 1 前言 单例模式是指在内存中有且只会创建一次对象的设计模式,在程序中多次使用同一个对象且作用相同的时候,为了防止频繁的创建对象,单例模式可以让程序在内存中创建一个对象,让所有的调用者都共享这一单例对象。单例模式的类型有两种:懒汉式和饿汉式。 2 单例模式类型 饿汉式:在类加载的时候已经创建好该单例对象。 懒汉.

爪哇人的博客 7938

单例模式详解

一、什么是单例模式 单例模式是Java中最简单的设计模式之一。这种类型的设计模式属于创建者模式,它提供了一种访问对象的最佳方式。 这种设计模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一对象的方式,可以直接访问,不需要实例化该类的对象。 二、单例模式的结构 单例类:只能创建一个实例的类 访问类:使用单例类的类 三、单例模式分类 饿汉式:类加载就会导致该单实例对象被创建 懒汉式:类加载不会导致该单实例对象被创...

欢迎一起学习交流 2万+

XianYuAutoDeliveryX:基于闲鱼API与大模型的智能自动发货系统实践

本文详细介绍了如何利用XianYuAutoDeliveryX系统,结合闲鱼API与大语言模型,构建一个智能自动发货解决方案。该系统能实现买家付款后秒级自动发货,并通过对接ChatGPT等大模型智能回复买家咨询,有效解放卖家时间,提升虚拟商品店铺的运营效率和客户体验。

bush的博客 1015

一文带你彻底搞懂设计模式之单例模式!!由浅入深,图文并茂,超超超详细的单例模式讲解!!

本篇文章通过图文形式,由浅入深,详细讲解了设计模式中的单例模式的应用

祝你身体健康,美满幸福 1万+

iPhone用户必看:TrollStore巨魔商店在线安装保姆级教程(iOS 14-16.6.1适用)

本文为iOS 14至16.6.1系统的iPhone用户提供了一份详细的TrollStore(巨魔商店)在线安装教程。文章从核心原理、安装前准备讲起,逐步详解了通过Safari浏览器获取安装器、信任企业证书、部署TrollStore及关键后置配置的全过程,并附带了常见问题排错指南,帮助用户安全、高效地实现无需越狱安装第三方应用。

h0i1j2k3l的博客 1991

医学图像中的小目标病灶检测难题:我的硕士研究总结与思考

医学图像中的小目标检测和分割,主要指在CT、MRI、超声等医学影像中识别和分割微小病灶或细小结构。这些小目标通常体积小、边界模糊、特征不明显,却往往是关键病灶,例如肺部小结节、脑微出血、乳腺微钙化等。

weixin_45638136的博客 2370

JUC编程(三)

1.常用的辅助类 CountDownLatch /** * CountDownLatch 减法计数器 * */ public class Demo17 { public static void main(String[] args) throws InterruptedException { // CountDownLatch 默认的初始值 Count...

weixin_44744155的博客 144

01|无代码开发 | 如何使用Zion实现导航网站制作

以上就是我制作导航网站的心得,分享给大家,作为一个小白想要独立搭建一个网站还是比较困难的,而在Zion不仅可以用可视化的方法进行搭建,甚至还可以一键发布,不用考虑服务器域名啥的问题,真是太方便了。

2301_76262110的博客 1390

JAVA设计模式——单例模式八种方式

目录 单例模式简介: 应用场景: 单例设计模式的八种方式: 1、饿汉式(静态常量) 2、饿汉式(静态代码块) 3、懒汉式(线程不安全) 4、懒汉式(线程安全,同步方法) 5、懒汉式(线程安全,同步代码块) 6、双重检查(推荐使用) 7、静态内部类(推荐使用) 8、枚举(推荐使用) 单例模式在JDK应用的源码分析 单例模式注意事项和细节说明 单例模式简介: 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供

龍弟-idea的博客 7110

可变形卷积(Deformable Conv)原理解析与torch代码实现

图6为可变形卷积示意图。图1所示为普通卷积在输入特征图上进行卷积计算的过程,卷积核大小为3*3,在输入特征图尺寸为7*7上进行卷积,将卷积核权重与输入特征图对应位置元素相乘并求和得到输出特征图元素,按一定方式滑动窗口就能计算得到整张输出特征图。图6所示,在input feature map上普通卷积操作对应卷积采样区域是一个卷积核大小的正方形(绿框),而可变形卷积对应的卷积采样区域为一些蓝框表示的点,这就是可变形卷积与普通卷积的区别。先来一张图感受一下,图3为标准卷积与可变形卷积的卷积示例。

panghuzhenbang的博客 5万+

《Scratch图形化等级考试(1~4级)历届真题解析》专栏总目录

❤️ 专栏名称:《🌸 专栏介绍:中国电子学会《全国青少年软件编程等级考试》Scratch图形化等级考试(1~4级)历届真题解析。🚀 订阅专栏:原价 99.9,🔥 火爆订阅中 🔥,限时 19.9。订阅后可阅读专栏内所有文章,本专栏持续更新中,欢迎订阅!

人生就是一个不断学习的过程 1万+

【C++】八大常见的设计模式

本文将讲解几种常见的设计模式,并使用C++编写相应的代码示例。适配器模式将一个类的接口转换成客户端期望的另一个接口,消除由于接口不兼容而导致的类无法一起工作的问题。模板方法模式定义了一个算法的骨架,将一些步骤延迟到子类中实现,使得子类可以重新定义算法的步骤。建造者模式将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。懒汉式单例模式在第一次使用时初始化实例,懒加载,节省资源,但需要考虑线程安全。工厂模式用于创建对象的实例,而不需要指定具体的类。

Z1tai的博客 5917

MATLAB - 浮动基座机器人的逆运动学

本例演示如何解决以浮动底座为模型的机器人的逆运动学问题。浮动底座机器人可以在空间中自由平移和旋转,具有六个自由度。浮动基座机器人的逆运动学问题适用于空间应用,即使用安装在浮动和致动基座上的机械臂在空间操纵物体,也适用于躯干和腿部可在空间自由移动的行走机器人。请注意,刚体树对象表示具有固定基体的刚体树。这意味着刚体树的基体在世界中具有固定的位置和方向。您可以在基体上附加一个 “浮动 ”类型的刚体关节,为具有浮动基体的机器人建模,以用于动态模拟等某些应用。

机器人控制与仿真应用 2439

八大设计模式——单例模式

八大设计模式——单例模式。

pluto_ian的博客 82

Sigrity System SI Parallel Bus Analysis模式进行DDR3仿真分析操作指导-单个颗粒

Default Strobe Offset:DQS默认偏移时间,自动填充为0.5ns,即DQS默认偏移1/2UI,DQS滞后于DQ 1/2UI,让建立保持时间均分。WLO:写平衡偏移的数值,DataL是0ps,DataU是500ps,是根据WLOSkew自动定义的,可以认为是WLOSkew取整,也可以根据需要手动调整数值。注意AddCmd的UI=T,这里的Data Rate仍然是DQ的速率,并不是地址线的速率,地址线的速率=1/UI=1/2ns=0.5Gbps。

weixin_54787054的博客 366

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

在Spring 当中存在的八大模式

在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。

weixin_61635597的博客 998

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

【C++】 八大常见的设计模式-单例模式

设计模式是一种编写代码的方式,旨在解决常见的软件设计问题。这些模式提供了代码重用和易于维护的解决方案。本文将讲解几种常见的设计模式,并使用 C++ 编写相应的代码示例。

2301_77562764的博客 483

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【设计模式】(二、设计模式之八大单例模式的实现方式)

所谓类的单例设计模式,就是采取一定的手段保证在整个软件系统中,某个类只能存在一个实例,并且该类只提供一个静态方法获取到该类的实例,不提供方法给其创建实例。 一般对于一些比较重量级的,而且有一个实例就够用的,我们会将其设计成为单例模式,用于减轻系统的压力。 单例模式的八种方式: 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安全,同步方法) 懒汉式(线程安全,同步代码块) 双重检查 静态内部类 枚举 饿汉式(静态常量) public class ...

CoderOu 159

Spring中的八大设计模式详解

本文介绍了Spring框架中常用的四种设计模式及其实现方式: 单例模式 - Spring默认以单例方式管理Bean,通过容器确保全局唯一实例,示例展示商品库存管理类的单例实现。 工厂模式 - 通过BeanFactory和ApplicationContext创建对象,示例演示商品服务工厂根据不同类型创建不同产品服务。 代理模式 - Spring AOP基于代理模式实现,示例展示通过切面在商品销售前后添加日志功能。 适配器模式 - 如HandlerAdapter适配不同处理器,示例展示旧商品服务接口适配到新系统

1加1等于的博客 285

深入剖析C++单例模式的八种实现演进与工程实践

单例模式就像全局变量,使用前要三思。但当确实需要时,应该用最安全的方式实现它。

ALex_zry的博客 1299

python单例模式代码-python设计模式之单例模式

无论是在python代码中,还是面试中单例设计模式都是经常被问到和使用的,例如面试中会让你用代码实现单例模式分几种不同的方式,或者问你在平常工作中哪些地方有用到单例设计模式,然后深入探讨。在本文中我将针对这两个问题来回答和用python代码来编写我们的单例模式。首先,我们要了解什么是单例模式--官方解释是:确保一个类只有一个实例(也就是类的对象),并且提供一个全局的访问点(外部通过这个访问点来访问...

weixin_37988176的博客 453

PHP八大设计模式

PHP命名空间可以更好地组织代码,与Java中的包类似。 Test1.php <?php namespace Test1;//命名空间Test1 function test(){ echo __FILE__; } Test2.php <?php namespace Test2; //命名空间Test2 function test(){ echo __FILE__;//打印当前文件所

flitrue的博客 4万+

C++设计模式——八大设计原则

引言 在学习的过程中,我通常会分为三步,吸收消化、表达出来、教会他人。如果能达到通俗易懂的方式教会他人,那必定对该知识点十分熟悉。所以我也想尝试通过将设计模式给写出来、表达出来、使自己对设计模式有更加深刻的一个理解,同时也给别人参考学习。如果有不正确的地方,欢迎纠正。 概述 设计模式体现的是一种思想,理解和掌握了设计模式,并不是说记住了 23 种设计场景和解决策略(实际上这也是很重要的一笔财富),...

赵小厨的博客 1529

八大最常用的JavaScript设计模式

八大最常用的JavaScript设计模式 设计模式(Design pattern) 是解决软件开发某些特定问题而提出的一些解决方案也可以理解成解决问题的一些思路。通过设计模式可以帮助我们增强代码的可重用性、可扩充性、 可维护性、灵活性好。我们使用设计模式最终的目的是实现代码的 高内聚 和 低耦合。通俗一点讲的话 打比方面试官经常会问你如何让代码有健壮性。其实把代码中的变与不变分离,确保变化的部分灵活、不变的部分稳定,这样的封装变化就是代码健壮性的关键。而设计模式的出现,就是帮我们写出这样的代码。 设计模式就

sdasadasds的博客 1104

JAVA设计模式-单例模式(八种方式实现)

设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。 目录 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。 单例模式有八种方式: 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安全,同步方法) 懒汉式(线程安全,同步代码块) 双重检查 静态内部

墨水记忆 847
上一篇: Java设计模式 - 概述
下一篇: 原型模式、装饰者模式、建造者模式原理及实例
pox21s
博客等级 码龄7年 7粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值