【单例模式】饿汉模式和懒汉模式的单例模式

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


一、设计模式

设计模式是一种在软件设计中经过验证的解决问题的方案或者模版。它们是从实践中总结出来的,可以帮助解决常见的设计问题,提高代码的重用性、维护性和扩展性。

设计模式可以分为三大类:

  1. 创建型模式(Creational Patterns):创建型模式关注对象的实例化过程,包括如何创建、组合和表示对象。常见的创建型模式有单例模式、工厂模式、抽象工厂模式、建造者模式和原型模式等。

  2. 结构型模式(Structural Patterns):结构型模式关注对象的组合和关系,以实现更大的结构和功能。常见的结构型模式有适配器模式、装饰器模式、代理模式、组合模式、享元模式和桥接模式等。

  3. 行为型模式(Behavioral Patterns):行为型模式关注对象之间的通信和协作,以实现特定的行为和交互模式。常见的行为型模式有观察者模式、策略模式、模板方法模式、迭代器模式、状态模式和命令模式等。

每种设计模式都有其特定的应用场景和优势,可以根据需求选择适当的模式。设计模式可以提供一些常用的解决方案,帮助开发人员更好地组织代码结构、降低耦合度、增加灵活性和可维护性

二、单例模式

2.1 单例模式的概念与特点

单例模式(Singleton Pattern)是一种创建型设计模式,用于确保一个类只存在一个实例,并提供全局访问点来访问该实例

在软件开发中,有些类只需要拥有一个全局实例,例如日志记录器、数据库连接池、线程池等。使用单例模式可以确保这些类只被实例化一次,从而节省系统资源,避免不必要的对象的创建和销毁

单例模式通常具有以下特点:

  1. 私有构造方法:单例类的构造方法是私有的,这样做的目的是为了防止外部代码直接实例化该类对象
  2. 静态访问方法:单例模式提供一个静态方法,用于获取单例实例。这个方法通常被命名为getInstance()
  3. 线程安全性:单例模式需要考虑多线程环境下的线程安全问题。确保在多线程环境下获取单例实例的方法是线程安全的,可以使用同步机制和双重检查锁(Double-Checked Locking)等方式实现。
  4. 全局访问:单例模式提供单例实例的全局访问,其他代码可以通过调用单例类的访问方法来获取实例。

单例模式可以带来一些优点,如减少内存开销、统一管理全局资源、提供全局访问点等。然而,过度使用单例模式可能导致代码的可测试性和可扩展性下降,因此在设计和应用中需要谨慎使用。

2.2 饿汉模式和懒汉模式

饿汉模式(Eager Initialization)懒汉模式(Lazy Initialization) 是两种常见的单例模式实现方式。

饿汉模式:

  • 在饿汉模式中,单例实例在类加载时就被创建,并在整个程序运行期间保持不变。因此,它的实例化是立即发生的,不需要延迟加载。
  • 饿汉模式的实现简单直接,可以通过将构造函数设为私有并创建一个静态的、final的实例来实现。通过静态方法或直接访问实例变量,其他代码可以获得该实例。
  • 饿汉模式是线程安全的,因为实例在类加载时就被创建,不存在多线程环境下的竞争条件
  • 由于实例在类加载时就创建,可能会导致资源的浪费,尤其是在实例很大或者需要耗费较多资源的情况下

懒汉模式:

  • 在懒汉模式中,单例实例在第一次使用时才被创建,延迟实例化。因此,它的实例化是在需要时发生的,具有延迟加载的特性。
  • 懒汉模式的实现通常涉及使用双重检查锁机制或者使用内部类来实现延迟加载和线程安全
  • 懒汉模式可以避免在应用程序启动时就创建实例,节省了资源。然而,在多线程环境中需要考虑线程安全性,特别是在第一次创建实例时需要进行同步控制,以避免多个线程同时创建多个实例的问题。

根据以上的定义可以得出,饿汉模式适用于实例创建和初始化的成本较低、资源占用较小的情况懒汉模式适用于实例创建和初始化的成本较高、资源占用较大的情况,并且希望在需要时才进行实例化。同时,在多线程环境下,需要考虑线程安全性和性能等因素进行选择。

三、单例模式的实现

3.1 饿汉模式的单例模式

恶汉模式的代码如下:

class Singleton{
    // 此处,先把这个实例创建出来
    private static Singleton instance = new Singleton();

    // 如果要使用这个实例,统一通过 Singleton.getInstance() 方式获取
    // 饿汉模式只涉及到读操作,因此是线程安全的
    public static Singleton getInstance(){
        return instance;
    }

    // 为了避免 Singleton 类不小心被复制出多份
    // 把构造方法设置为 private,在类外面就无法通过 new 的方式来创建这个 Singleton 实例了
    private Singleton(){}
}
  • 在这个实现中,单例实例 instance 在类加载阶段就被创建,并且通过静态方法 getInstance() 返回该实例。

  • 饿汉模式的实现确保了在整个程序运行期间只有一个实例存在,并且在需要时立即获得该实例。由于实例在类加载时就被创建,所以在多线程环境下也是线程安全的。

  • 私有的构造方法确保了在类外部无法通过 new 关键字创建该类的实例,从而限制了实例的数量。

3.2 懒汉模式的单例模式

单线程版懒汉模式的代码实现:

class Singleton {
    private static Singleton instance = null;

    private Singleton(){}

    public static Singleton getInstance() {
        if(instance == null){
        	instance = new Singleton();
        }
        return instance;
    }
}

上面的代码实现了单线程环境下的懒汉模式单例模式。

在这个实现中,getInstance() 方法首先检查 instance 是否为 null,如果为 null,则通过私有的构造函数创建一个新的实例,并将其赋值给 instance 变量。在后续调用 getInstance() 方法时,由于 instance 已经被赋值,直接返回该实例。

这种实现方式在单线程环境下是可行的,能够保证只有一个实例被创建并被返回。但是在多线程环境下,可能会出现问题,多个线程同时通过 instance == null 的判断条件进入,导致多次创建实例,违反了单例模式的原则。

因此,在多线程环境下,需要对该实现进行改进,以保证线程安全性。常见的方式是引入同步机制,如双重检查锁或使用 synchronized 关键字,来确保只有一个线程能够创建实例。

多线程版:

class Singleton{

    // 存在指令重排序问题。
    // 加上 volatile 关键字保持 instance 内存可见性,禁止指令重排
    private volatile static Singletoninstance = null;

    // 懒汉模式存在现线程安全
    // 解决方法:加上 synchronized
    // 存在的问题:这里的加锁只是在new对象之前加锁才是有必要的,后面就一直是读操作,没有加锁的必要

    // 改进:
    // 使用双重 if 判定, 降低锁竞争的频率
    // 给 instance 加上了 volatile.

    public static Singleton getInstance() {
        if (null == instance) { // 判断是否加锁
            // 当 instance 为空时才加锁
            synchronized (Singleton.class) {
                if (null == instance) { // 判断是否创建对象
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
    
    private Singleton() {
    }
}

以上代码实现了多线程环境下的懒汉模式单例模式,并对其进行了改进。

在这个实现中,使用了 双重检查锁(Double-Checked Locking) 机制和 volatile 关键字来解决多线程环境下的线程安全和指令重排序问题。

instance 声明为 volatile,可以保证线程之间对 instance 的可见性和禁止指令重排序,避免在实例化过程中的并发问题。因为在早期的 Java 版本中存在双重检查锁失效的问题。为了避免这个问题,建议使用 Java 5 及以上版本,并将 instance 变量声明为 volatile文章来源地址https://www.toymoban.com/news/detail-571887.html

到了这里,关于【单例模式】饿汉模式和懒汉模式的单例模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列

    目录 1、单例模式 1.1、饿汉模式 2.1、懒汉模式  2、阻塞队列 2.1、BlockingQueue 阻塞队列数据结构 对框架和设计模式的简单理解就是,这两者都是“大佬”设计出来的,让即使是一个代码写的不太好的“菜鸡程序员”也能写出还可以的代码。 设计模式也可以认为是对编程语言语

    2024年03月23日
    浏览(82)
  • Java单例模式的五种实现方式 懒汉式 饿汉式 双重校验锁 静态变量 静态内部类 枚举实现单例模式等

    Java单例模式是一种设计模式,用于确保一个类只有一个实例,并提供全局访问点以获取该实例。它通常用于需要共享资源或控制某些共享状态的情况下。 懒汉式:在类加载的时候就创建对象,要再调用方法时才创建对象,减少内存开销。 饿汉式:再类加载的时候就实例化对

    2024年04月27日
    浏览(26)
  • 设计模式之单例模式(懒汉, 饿汉)

    单例模式是一种常用的软件设计模式, 该模式的主要目的是确保某一个类在内存中只能有一个实例对象, 通过单例模式的方法创建的类在当前进程中只有一个实例对象. 常见的单例模式有两种: 饿汉式, 这里的 “饿” 意义表述不够清晰, 用 “急” 来表述意义更加容易联想一些

    2024年02月22日
    浏览(40)
  • 单例模式(饿汉式单例 VS 懒汉式单例)

    所谓的单例模式就是保证某个类在程序中只有一个对象 1.构造方法私有化(保证对象的产生个数)         创建类的对象,要通过构造方法产生对象        构造方法若是public权限,对于类的外部,可以随意创建对象,无法控制对象个数       构造方法私有化,这样类的外

    2024年02月09日
    浏览(31)
  • 单例模式(懒汉式和饿汉式)

    单例模式是指保证某个类在整个软件系统中只有一个对象实例,并且该类仅提供一个返回其对象实例,由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁地创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显。 在计算

    2024年02月13日
    浏览(36)
  • 单例模式:懒汉式和饿汉式

    目录 懒汉模式和饿汉模式 区别 示例 懒汉模式线程不安全 懒汉模式线程安全  懒汉模式内部静态变量线程安全 饿汉式线程安全 指的是在系统生命周期内,只产生一个实例。 分为 懒汉式 和 饿汉式 创建时机和线程安全 线程安全 :多线程共享资源的过程中,线程安全通过同

    2024年02月16日
    浏览(33)
  • JavaEE:单例模式(饿汉模式和懒汉模式)精讲

    前言 什么是单例模式? 其实用通俗的话就是程序猿约定俗成的一些东西,就比如如果你继承了一个抽象类,你就要重写里面的抽象方法,如果你实现了一个接口,你就要重写里面的方法。如果不进行重写,那么编译器就会报错。这其实就是一个规范。 而单例模式能保证某个

    2024年02月04日
    浏览(31)
  • 自学设计模式(类图、设计原则、单例模式 - 饿汉/懒汉)

    设计模式需要用到面向对象的三大特性——封装、继承、多态(同名函数具有不同的状态) UML类图 eg.—— 描述类之间的关系(设计程序之间画类图)  +: public; #: protected; -: private; 下划线: static 属性名:类型(=默认值) 方法和变量分开------- 虚函数斜体,纯虚函数在虚函数类

    2024年02月11日
    浏览(27)
  • 【多线程案例】单例模式(懒汉模式和饿汉模式)

    提起单例模式,就必须介绍设计模式,而设计模式就是在软件设计中,针对特殊问题提出的解决方案。它是多年来针对一些常见的问题的解决方法,具有良好的可复用性、可扩展性和可维护性。 标准的设计模式有23种,单例模式就是最常见的一种,其目的是确认一个类只有一

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

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

    2024年02月21日
    浏览(43)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包