单例设计模式

简介: 单例模式,饿汉式,懒汉式

单例设计模式

简介

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

代码讲解

首先需要知道的是单例模式分为两种创建方式:

  1. 饿汉式

    • 类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建。
  2. 懒汉式

    • 类加载就会导致该单实例对象被创建。

饿汉式

首先需要知道的就是,饿汉式是线程安全的,缺点就是可能造成内存的浪费问题。

方式一(静态变量法)

代码讲解

public class Singleton {
    // 首先的第一步就是把构造方法定义为
    // 私有变量
    private Singleton(){};

    // 在成员位置使用静态方法创建该类
    private static Singleton instance = new Singleton();

    // 对外提供静态方法获取该对象
    public static Singleton getInstance() {
        return instance;
    }
}

代码分析
该方法是把instance对象定义为static静态成员变量,该对象会随着类的加载而创建,这样会导致一个问题,如果该对象所占用的内存比较大的话,那么如果这个对象一直得不到使用,会造成内存的严重的浪费问题。

方式二(静态代码块方式)

代码讲解

package com.example.springbootstudy;

public class Singleton {
    // 首先的第一步就是把构造方法定义为
    // 私有变量
    private Singleton(){};

    // 在成员位置使用静态方法创建该类
    private static Singleton instance;

    // 通过静态代码块的成员初始化表的形式 进行创建
    static {
        instance = new Singleton();
    }
    // 对外提供静态方法获取该对象
    public static Singleton getInstance() {
        return instance;
    }
}

代码分析
第二种方式相比于,第一种方式的区别在于,生成的方式不一样,是在静态代码块中生成的,但是产生的结果是一样的,就是对象随着类的加载而创建,也存在内存浪费问题。

懒汉式

方式一(线程不安全)

代码讲解

public class Singleton {
    // 首先的第一步就是把构造方法定义为
    // 私有变量
    private Singleton(){};

    // 在成员位置使用静态方法创建该类
    private static Singleton instance;

    // 对外提供静态方法获取该对象
    public static Singleton getInstance() {
        // 这个单例还没有被创建 那么就创建一个
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

代码分析
上面的这种方式在单线程的时候是没有问题的,但是当运用到多线程环境的时候,就会出现线程安全问题,多个空的instance对象同时进行请求,那么就会出现线程安全问题。

方式二(线程安全,利用锁来实现)

代码讲解

public class Singleton {
    // 首先的第一步就是把构造方法定义为
    // 私有变量
    private Singleton(){};

    // 在成员位置使用静态方法创建该类
    private static Singleton instance;

    // 对提供的静态方法获取该对象
    // 通过上锁的方式来解决多线程不安全的问题
    public static synchronized Singleton getInstance() {
        // 这个单例还没有被创建 那么就创建一个
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

代码分析
该方法虽然解决了线程安全问题,但是通过在getInstance()方法上面加上synchronized关键字,会大大降低该方法的执行效率,然后我们分析可知,线程安全问题,主要是会在初始化instance的时候出现,当初始化完成之后,就不存在了,所以前辈们就提出了这种方案。

方式三(双重检查锁)

代码讲解

public class Singleton {
    // 首先的第一步就是把构造方法定义为
    // 私有变量
    private Singleton(){};

    // 在成员位置使用静态方法创建该类
    private static Singleton instance;

    // 对提供的静态方法获取该对象
    // 通过上锁的方式来解决多线程不安全的问题
    public static Singleton getInstance() {
        // 第一次判断 如果instance不为空 那么就直接返回实例
        // 不进入抢锁阶段
        if (instance == null){
            synchronized (Singleton.class){
                // 反之当进入抢锁阶段后 再判断一次
                // 对象是否为空
                // 通过这种双重检测的方式,大大提高了效率
                if(instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

代码分析
该方法是一种非常好的单例模式,在性能与线程安全上都实现了很好的优化,但是还是存在着问题,比如在多线程的情况下,还是会出现空指针问题,该问题是JVM本身的问题,JVM在实例化对象的时候会进行优化与指令重排序操作,从而导致空指针问题。
想要解决这个问题,只需要private static Singleton instance;,前面加上volatile关键字即可。
也就是private static volatile Singleton instance;

相关文章
|
7月前
|
设计模式
单例设计模式步骤
单例设计模式步骤
35 1
|
7月前
|
设计模式 安全 测试技术
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
147 0
|
7月前
|
设计模式 安全 Java
最简单的设计模式是单例?
单例模式可以说是Java中最简单的设计模式,但同时也是技术面试中频率极高的面试题。因为它不仅涉及到设计模式,还包括了关于线程安全、内存模型、类加载等机制。所以说它是最简单的吗?
82 3
最简单的设计模式是单例?
|
7月前
|
设计模式 安全 Java
【设计模式】2、设计模式分类和单例设计模式
【设计模式】2、设计模式分类和单例设计模式
59 0
|
7月前
|
设计模式 消息中间件 安全
多线程编程设计模式(单例,阻塞队列,定时器,线程池)(二)
多线程编程设计模式(单例,阻塞队列,定时器,线程池)(二)
63 1
|
7月前
|
设计模式 Java
26、Java 简单实现单例设计模式(饿汉式和懒汉式)
26、Java 简单实现单例设计模式(饿汉式和懒汉式)
58 2
|
7月前
|
设计模式 安全 Java
在Java中即指单例设计模式
在Java中即指单例设计模式
41 0
|
17天前
|
设计模式 前端开发 JavaScript
JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式
本文深入探讨了JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式,结合电商网站案例,展示了设计模式如何提升代码的可维护性、扩展性和可读性,强调了其在前端开发中的重要性。
22 2
|
3月前
|
设计模式 存储 安全
设计模式——设计模式介绍和单例设计模式
饿汉式(静态常量)、饿汉式(静态代码块)、懒汉式(线程不安全)、懒汉式(线程安全,同步方法)、懒汉式(线程不安全,同步代码块)、双重检查(推荐,线程安全、懒加载)、静态内部类(推荐)、枚举(推荐)
设计模式——设计模式介绍和单例设计模式
|
4月前
|
设计模式 JavaScript 前端开发
从工厂到单例再到策略:Vue.js高效应用JavaScript设计模式
【8月更文挑战第30天】在现代Web开发中,结合使用JavaScript设计模式与框架如Vue.js能显著提升代码质量和项目的可维护性。本文探讨了常见JavaScript设计模式及其在Vue.js中的应用。通过具体示例介绍了工厂模式、单例模式和策略模式的应用场景及其实现方法。例如,工厂模式通过`NavFactory`根据用户角色动态创建不同的导航栏组件;单例模式则通过全局事件总线`eventBus`实现跨组件通信;策略模式用于处理不同的表单验证规则。这些设计模式的应用不仅提高了代码的复用性和灵活性,还增强了Vue应用的整体质量。
60 1