大话设计模式——9.单例模式(Singleton Pattern)

简介

确保一个类只有一个实例,并提供全局访问点来获取该实例,是最简单的设计模式。

UML图:
在这里插入图片描述
单例模式共有两种创建方式:

  • 饿汉式(线程安全)

提前创建实例,好处在于该实例全局唯一,不存在线程冲突;坏处在于未使用时也会占用内存资源。

  • 懒汉式(原生写法存在线程冲突问题)

将实例的创建延迟到第一次使用时进行,相当于懒加载

创建步骤:

  • 私有化构造器
  • 提供唯一的全局访问接口
一、饿汉式
  1. 饿汉对象:
public class HungrySingleton {

    // 创建实例,类加载时已经确定实例,不存在线程冲突
    private static final HungrySingleton newInstance = new HungrySingleton();

    // 私有化构造器
    private HungrySingleton() {

    }

    public void processOn() {
        System.out.println("饿汉单例模式");
    }

    /**
     * 提供对外唯一访问实例的方法
     *
     * @return
     */
    public static HungrySingleton getInstance() {
        return newInstance;
    }
}
  1. 运行
public class Main {

    public static void main(String[] args) {
        HungrySingleton.getInstance().processOn();
        HungrySingleton hungrySingleton01 = HungrySingleton.getInstance();
        HungrySingleton hungrySingleton02 = HungrySingleton.getInstance();
        System.out.println(hungrySingleton02 == hungrySingleton01);
    }
}

在这里插入图片描述

二、懒汉式
  1. 原生写法
public class LazySingleton {


    // 实例对象
    private static LazySingleton instance = null;

    private LazySingleton() {
    }

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

存在线程安全隐患,多个线程进入可能会重复创建实例
在这里插入图片描述
在这里插入图片描述

改造

  • 方式1:同步方法
public class LazySingleton {


    // 实例对象
    private static LazySingleton instance = null;

    private LazySingleton() {
    }

    /**
     * 同步锁,每次只能允许一个线程进行获取
     * @return
     */
    public static synchronized LazySingleton getInstanceSafely(){
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

ps:改方式虽然可以确保线程安全,但是由于锁的粒度较大,高并发情况下系统性能会降低。

  • 方式2:同步代码块,使用volatile禁止指令重排,确保赋值时的原子操作同时使用DCL双重检查锁定 (Double-Checked-Locking),在多线程情况下保持高性能
public class LazySingleton {


    // 实例对象,禁止指令重排,确保原子操作
    private static volatile LazySingleton instance = null;

    private LazySingleton() {
    }
    
    /**
     * 同步锁,每次只能允许一个线程进行获取
     *
     * @return
     */
    public static LazySingleton getInstanceSafely02() {
        if (null == instance) {
            synchronized (LazySingleton.class) {
                // DCL双重检查锁定 
                if (null == instance) {
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
}
总结

对象不复杂时,建议使用饿汉式。其他情况下使用懒汉式性能较好。

相关推荐

  1. .NET 设计模式模式SingletonPattern

    2024-04-07 16:42:01       38 阅读
  2. 设计模式

    2024-04-07 16:42:01       63 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-07 16:42:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-07 16:42:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-07 16:42:01       87 阅读
  4. Python语言-面向对象

    2024-04-07 16:42:01       96 阅读

热门阅读

  1. dfs,LeetCode 1026. 节点与其祖先之间的最大差值

    2024-04-07 16:42:01       39 阅读
  2. QT各种锁及线程同步应用

    2024-04-07 16:42:01       33 阅读
  3. C语言形参与实参

    2024-04-07 16:42:01       43 阅读
  4. Elasticsearch如何选择版本

    2024-04-07 16:42:01       37 阅读
  5. socket套接字函数

    2024-04-07 16:42:01       34 阅读
  6. ss命令

    2024-04-07 16:42:01       36 阅读
  7. video替换webRtc视频流

    2024-04-07 16:42:01       42 阅读
  8. vim编辑器基本使用教程

    2024-04-07 16:42:01       35 阅读
  9. 第五届信大超越杯团体赛部分题解

    2024-04-07 16:42:01       37 阅读
  10. 练习3-7 成绩转换

    2024-04-07 16:42:01       33 阅读
  11. 15届蓝桥备赛(5)

    2024-04-07 16:42:01       33 阅读
  12. 第十四届蓝桥杯省赛大学C组(C/C++)三国游戏

    2024-04-07 16:42:01       42 阅读