【设计模式学习1】什么是单例模式?单例模式的几种实现。

这篇具有很好参考价值的文章主要介绍了【设计模式学习1】什么是单例模式?单例模式的几种实现。。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、什么是单例模式

单例模式是在内存中只创建一个对象的模式,它保证一个类只有一个实例。

二、单例模式的几种实现

(一)懒汉式单例模式

/**
 * 懒汉式单例模式
 * (懒加载,需要的时候在去加载)
 * 优点:需要SingleObject时,才会去实例化,节省空间
 * 缺点:在多线程环境下,getSingleObject() 方法并不是线程安全的
 */

public class SingleObject {
    //私有化对象(未实例化)
    private static SingleObject object;

    //私有化构造方法
    private SingleObject() {};

    //获取私有化对象
    public static SingleObject getSingleObject() {
        //bean为null才去实例化,否则直接返回。
        if (object == null) {
            object = new SingleObject();
        }
        return object;
    }
}

(二)饿汉式单例模式

/**
 * 饿汉式单例模式
 * (线程安全,但会造成资源浪费)
 * 优点:在类加载时候创建实例,不存在线程安全问题
 * 缺点:占用系统资源,如果这个实例没有被用到,则会造成资源浪费
 */
public class Single {
    //私有化对象(已实例化)
    private static Single object = new Single();

    //私有化构造方法
    private Single() {};

    //获取私有化对象
    public static Single getSingle() {
        return object;
    }

}

(三)双重校验加锁式单例模式(线程安全)

public class SingleObject{
    //volatile关键字防止指令重排序造成的空指针异常(通过插入特定的内存屏障的方式来禁止指令重排序)
    private static volatile SingleObject object;

    //私有构造方法
    private SingleObject() {}

    public static SingleObject getSingleObject() {
        //第一次检查防止每次获取bean都加锁
        if (object == null) {
            //加锁,防止第一次创建实例化时,并发线程多次创建对象
            synchronized (SingleObject.class) {
                //第二次检查判断对象没有实例化,则进行对象的实例化
                if (object == null) {
                    object = new SingleObject();
                }
            }
        }
        return object;
    }
}

三、问题分析

(一)懒汉模式为什么会有线程安全问题?

【设计模式学习1】什么是单例模式?单例模式的几种实现。,设计模式,单例模式,java
如上图所示,多线程情况下,在时刻T,线程A和线程B都判断single为null,从而进入if代码块中都执行了new Single()的操作创建了两个对象,就和我们当初的单例初衷相悖而行。

(二)为什么要进行两次判空,他们的作用分别是什么?加锁的作用是什么?

1、第一次判空目的:为了缩小锁的粒度,避免每次获取实例都需要进行加锁。
2、加锁目的:在首次获取对象实例时,防止并发线程多次创建对象。
3、第二次判空目的:如果对象没有进行实例化,则进行对象实例化操作

(三)volatile关键字修饰对象的作用是什么?

volatile关键字防止指令重排序造成的空指针异常(通过插入特定的内存屏障的方式来禁止指令重排序)

指令重排序是指:JVM在保证最终结果正确的情况下,可以不按照程序编码的顺序执行语句,尽可能提高程序的性能。

创建一个对象,在JVM中会经过三步:

  • (1)为object对象分配内存空间
  • (2)初始化object对象
  • (3)将object指向分配好的内存空间

由于 JVM 具有指令重排的特性,执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getSingleObject() 后发现 object不为空,因此返回 object,但此时 object还未被初始化,就会出现空指针异常。文章来源地址https://www.toymoban.com/news/detail-609472.html

到了这里,关于【设计模式学习1】什么是单例模式?单例模式的几种实现。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python入门【​编辑、组合、设计模式_工厂模式实现 、设计模式_单例模式实现、工厂和单例模式结合、异常是什么?异常的解决思路 】(十七)

    👏作者简介:大家好,我是爱敲代码的小王,CSDN博客博主,Python小白 📕系列专栏:python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀 🔥如果感觉博主的文章还不错的

    2024年02月14日
    浏览(44)
  • 设计模式学习(一)单例模式补充——单例模式析构

    目录 前言 无法调用析构函数的原因 改进方法 内嵌回收类 智能指针 局部静态变量 参考文章 在《单例模式学习》中提到了,在单例对象是通过 new 动态分配在堆上的情况下,当程序退出时,不会通过C++的RAII机制自动调用其析构函数。本文讨论一下这种现象的原因以及

    2024年03月19日
    浏览(53)
  • 【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式

    🍎 个人博客: 个人主页 🏆 个人专栏: JAVA ⛳️   功不唐捐,玉汝于成 目录 前言 正文 懒汉式(Lazy Initialization): 双重检查锁定(Double-Checked Locking): 结语 我的其他博客 在软件设计中,单例设计模式是一种重要的设计思想,它确保了一个类只有一个实例,并提供了一

    2024年01月15日
    浏览(55)
  • 学习笔记-设计模式-创建型模式-单例模式

    一个类只有一个实例,并提供一个全局访问此实例的点,哪怕多线程同时访问。 单例模式主要解决了 一个全局使用的类被频繁的创建和消费 的问题。 单例模式的案例场景 数据库的连接池不会反复创建 spring中一个单例模式bean的生成和使用 在我们平常的代码中需要设置全局

    2024年02月08日
    浏览(52)
  • 设计模式学习(一)单例模式补充——指令重排

    目录 前言 指令重排简介 指令重排对单例模式的影响 改进方法 std::call_once和std::once_flag std::atomic和内存顺序 局部静态变量 总结 参考文章 在《单例模式学习》中曾提到懒汉式DCLP的单例模式实际也不是线程安全的,这是编译器的指令重排导致的,本文就简单讨论一下指令重排

    2024年03月19日
    浏览(46)
  • DCL 单例模式设计为什么需要 volatile 修饰实例对象

     DCL 问题,是在基于双重检查锁设计下的单例模式中,存在不 完整对象的问题。而这个不完整对象的本质,是因为指令重排序导致的。 当我们使用 instance=new DCLExample()构建一个实例对象的时候,因为 new 这个操作并不是原子的。所以这段代码最终会被编译成 3 条指令: 为对象

    2024年02月08日
    浏览(49)
  • 113、单例Bean是单例模式吗?

    通常来说,单例模式是指在一个JVM中,一个类只能构造出来一个对象,有很多方法来实现单例模式,比如懒汉模式,但是我们通常讲的单例模式有一个前提条件就是规定在一个JVM中,那如果要在两个JVM中保证单例呢?那可能就要用分布式锁这些技术,这里的重点是,我们在讨

    2024年02月14日
    浏览(48)
  • 懒汉单例设计模式与饿汉单例设计模式

    单例模式即一个类确保只有一个对象,主要用于避免浪费内存 1 .饿汉单例设计模式 :拿到对象时,对象就早已经创建好了 写法: 把类的构造器私有 在类中自己创建一个对象,并赋值到一个变量 定义一个静态方法,返回自己创建的这个对象 2. 懒汉单例设计模式 :第一次拿到对象时

    2024年02月21日
    浏览(59)
  • 【设计模式】单例设计模式

    目录 1、前言 2、基本语法 2.1、懒汉式单例 2.2、饿汉式单例 2.3、双重检验锁单例模式 2.4、静态内部类单例模式 2.5、枚举单例模式 2.6、ThreadLocal单例模式 2.7、注册单例模式 3、使用场景 4、使用示例 5、常见问题 5、总结 单例模式是一种设计模式,它确保一个类只能创建一个实

    2024年02月09日
    浏览(44)
  • 【设计模式】单例模式|最常用的设计模式

    单例模式是最常用的设计模式之一,虽然简单,但是还是有一些小坑点需要注意。本文介绍单例模式并使用go语言实现一遍单例模式。 单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。 使用场景: 当类只能有一个实例而且可以从一个公开的众所周知的访

    2024年04月29日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包