首页 > 其他分享 >单例模式的五种实现方式

单例模式的五种实现方式

时间:2023-09-12 15:46:38浏览次数:38  
标签:SingleTon 模式 INSTANCE 五种 static private 单例 public

参考 https://blog.csdn.net/qq_42372017/article/details/121192445

1. 单例模式的四大原则

  1. 构造方法私有
  2. 以静态方法或者枚举返回实例
  3. 多线程环境下都是访问同一个实例
  4. 反序列化时不会重新构建对象

2. 单例模式通常有5种实现方法

2-1 饿汉模式

饿汉模式会在类初始化时就提前创建了对象,是一种以空间换取时间的方法,所以不存在线程安全问题。(记忆方法:一个人很饿,那他就会提前把食物准备好)

public class SingleTon {
    // 提前实例化
    private static SingleTon INSTANCE = new SingleTon();
    // 构造方法私有
    private SingleTon(){}
    
    public static SingleTon getInstance() {
        return INSTANCE;
    }
}

2-2 懒汉模式

懒汉模式会在方法被调用的时候才去创建对象,以时间换取空间,在多线程下存在线程安全问题,当多个线程调用getInstance()方法时可能都看到INSTANCE = null,从而导致多个线程去创建对象,违背单例模式的原则。

public class SingleTon {
    private static SingleTon INSTANCE = null;
    private SingleTon() {}

    public static SingleTon getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new SingleTon();
        }
        return INSTANCE;
    }
}

2-3 双重锁懒汉模式(DCL)

DCL模式是对懒汉模式的改进,第一次判断 INSTANCE == null是为了避免非必要加锁,只有在第一次加载的时候才会对Class对象进行加锁再实例化,这样既可以节约内存空间,又能保证线程安全。

public class SingleTon {
    private static SingleTon INSTANCE = null;
    private SingleTon() {}

    public static SingleTon getInstance() {
        if (INSTANCE == null) {
            synchronized (SingleTon.class) {
                if (INSTANCE == null) {
                    INSTANCE = new SingleTon();
                }
            }
        }
        return INSTANCE;
    }
}

但是因为 JVM 存在指令重排的功能,DCL也会存在线程不安全的情况。因为INSTANCE = new SingleTon();实例化对象看似只有一行代码,但其实在 JVM 中是分为三步执行的:

  1. 在堆内存中开辟内存空间;
  2. 在分配的内存空间中实例化SingleTon的各个参数;
  3. 将对象指向堆内存空间。

由于 JVM 的指令重排原因,所以有可能2还没执行就先执行了3,如果此时再被切换到线程B上,由于执行了3,INSTANCE != null已经非空了,会被直接拿出来用,这样的话,就会出现异常。这个就是著名的DCL失效问题。

具体解决方案是使用 volatile 关键字,可以防止指令重排,从而解决DCL失效问题:private volatile static SingleTon INSTANCE = null;

2-4 静态内部类模式(常用)

使用静态内部类的优点是:外部类加载时并不需要立即加载内部类,内部类不被加载则不用去初始化INSTANCE,故而不占内存。即当SingleTon第一次被加载时,并不需要去加载SingleTonHolder类,只有当获取INSTANCE实例,也就是getInstance()方法第一次被调用时,才会导致虚拟机加载SingleTonHolder类,这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。
缺点:由于是静态内部类的形式去创建单例的,故外部无法传递参数进去,只能调用固定的构造函数。

public class SingleTon {
    private SingleTon() {}
    private static class SingleTonHolder {
        private static SingleTon INSTANCE = new SingleTon();
    }

    public static SingleTon getInstance() {
        return SingleTonHolder.INSTANCE;
    }
}

2-5 枚举模式(《Effective Java》推荐)

在《effective java》第83 条:慎用延迟初始化(这本书真的很棒)中说道,最佳的单例实现模式就是枚举模式。利用枚举的特性,让JVM来帮我们保证线程安全和单一实例的问题。

public enum SingleTon {
    INSTACE;
    public void doSomething() {
        System.out.println("doSomething");
    }
}
// 调用方法:
class Main {
    public static void main(String[] args) {
        SingleTon.INSTACE.doSomething();
    }
}

标签:SingleTon,模式,INSTANCE,五种,static,private,单例,public
From: https://www.cnblogs.com/yppah/p/17696358.html

相关文章

  • 设计模式-装饰器模式
    装饰器模式(文章目录)什么是装饰器模式  装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。为什么使用装饰器模式使用装饰者模式有如下好处:  1.避免了类爆炸问题,简化了设计  2.易于扩展,可以灵活组......
  • Android开发中常见的设计模式
    Android开发中常见的设计模式对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次。而在android开发中,必要的了解一些设计模式又是非常有必要的。对于想系统的学习设计模式的同学,这里推荐2本书。一本是HeadFirst系列的HeadH......
  • Padavan配置白名单模式及上网时间控制
    登录Padavan管理后台,高级设置--->防火墙--->mac访问控制--->mac访问控制模式【允许模式---仅列表中的设备可获取网络;拒绝模式---列表中的设备拒绝访问网络】,禁止访问路由器主机这项一定打开,不然试了下没效果,开了就是未在列表中的设备不能访问路由器,初次连接的设备也无法获取ip地......
  • 在.NET中实现事件驱动编程模式
    当在.NET中实现事件驱动编程模式时,你可以创建自定义事件和委托,然后让对象触发事件,以便其他对象可以订阅并响应这些事件。这种模式常用于构建可扩展和松散耦合的应用程序。以下是一个基本示例,演示如何在C#中实现事件驱动编程。步骤1:创建一个C#控制台应用程序首先,创建一个新的C#控......
  • Ubuntu Server 22.04 双网卡绑定 配置文件 Bond mode 1 : active-backup 主备模式
    UbuntuServer22.041.拓扑视图实例 2.备份配置文件修改前备份root@ax:~#cpetc/netplan/00-installer-config.yamletc/netplan/00-installer-config.yaml.orig修改配置文件,Ubuntu严格区分格式,空格缩进。简要说明:eno1-eno4,关闭dhcp;bond0只绑定eno1、eno2,实际可根据情况,绑定更多......
  • 软件设计模式系列之三———工厂方法模式
    1模式的定义工厂方法模式是一种常见的设计模式,属于创建型设计模式之一,它在软件工程中用于对象的创建。该模式的主要思想是将对象的创建过程抽象化,将具体对象的实例化延迟到子类中完成,以便在不同情况下可以创建不同类型的对象,而客户端代码不需要知道实际创建的对象类型。2举例......
  • "快速编辑模式"带来的命令行程序暂停问题
    在Windows下,"快速编辑模式"(QuickEditMode)允许用户通过点击和拖动来选择命令提示符窗口中的文本。但是,这可能会导致某些命令行程序暂停,直到用户按下Enter键。因此,某些用户可能希望禁用这个模式。要禁用"快速编辑模式",请按照以下步骤操作:打开命令提示符(cmd)。右......
  • 【23种设计模式】装饰模式(九)
    前言装饰模式,英文名称:DecoratorPattern。我第一次看到这个名称想到的是另外一个词语“装修”,我就说说我对“装修”的理解吧,大家一定要看清楚,是“装修”,不是“装饰”。在房子装修的过程中,各种功能可以相互组合,来增加房子的功用。类似的,如果我们在软件系统中,要给某个类型或者对象......
  • 【设计模式】观察者模式Observer:消息的订阅-发布
    (目录)观察者模式是一种非常流行的设计模式,也常被叫作订阅-发布模式。观察者模式在现代的软件开发中应用非常广泛,比如,商品系统、物流系统、监控系统、运营数据分析系统等。常说的基于事件驱动的架构,其实也是观察者模式的一种最佳实践。当观察某一个对象时,对象传递出的每一个行......
  • 5.前端设计模式之容器/展现模式
    Enforceseparationofconcernsbyseparatingtheviewfromtheapplicationlogic通过将视图层和应用逻辑分离实现关注点分离 这个有点像Java应用开发中经常看到的MVC架构模式,实现数据、业务逻辑和展示层分离。这个模式在React中需要两个组件实现:容器组件主要负责获取数据,获取......