单例模式的几种实现方式

单例模式(Singleton Pattern)是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点。这种模式在需要全局状态或者希望整个应用程序中某个对象只有一个实例时非常有用。

单例模式的关键特点包括:

  1. 唯一实例:单例类通过私有构造函数和静态实例变量确保只有一个实例被创建。
  2. 全局访问点:单例类提供一个公共的静态方法,允许其他对象获取到这个唯一实例的引用。
  3. 延迟初始化:单例实例可以在第一次使用时创建,也可以在类加载时立即创建。延迟初始化有助于节省资源,因为它允许系统在需要时才创建实例。
  4. 线程安全:在多线程环境中,单例模式需要确保线程安全,避免多个线程同时创建多个实例。

实现方案的话,我这里推荐三种:

1、枚举(推荐)

java 复制代码
public enum Singleton {
    INSTANCE;
    public void doSomething(String str) {
        System.out.println(str);
   }
}

《Effective Java》作者推荐的⼀种单例实现⽅式,简单⾼效,⽆需加锁,线程安全,可以避免通过 反射破坏枚举单例。

2、静态内部类(推荐)

java 复制代码
public class Singleton {
    // 私有化构造⽅法
    private Singleton() {
   }
    // 对外提供获取实例的公共⽅法
    public static Singleton getInstance() {
        return SingletonInner.INSTANCE;
   }
    // 定义静态内部类
    private static class SingletonInner{
        private final static Singleton INSTANCE = new Singleton();
   }
}

当外部类Singleton被加载的时候,并不会创建静态内部类SingletonInner的实例对象。只有当调 ⽤getInstance()⽅法时, SingletonInner才会被加载,这个时候才会创建单例对象INSTANCE 。 INSTANCE的唯⼀性、创建过程的线程安全性,都由 JVM 来保证。 这种⽅式同样简单⾼效,⽆需加锁,线程安全,并且⽀持延时加载。

3、双重校验锁

java 复制代码
public class Singleton {
    private volatile static Singleton uniqueInstance;
    // 私有化构造⽅法
    private Singleton() {
   }
    public  static Singleton getUniqueInstance() {
       //先判断对象是否已经实例过,没有实例化过才进⼊加锁代码
        if (uniqueInstance == null) {
            //类对象加锁
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
               }
           }
       }
        return uniqueInstance;
   }
}

uniqueInstance采⽤volatile关键字修饰也是很有必要的,uniqueInstance = new Singleton();这段 代码其实是分为三步执⾏: 1. 为uniqueInstance分配内存空间 2. 初始化uniqueInstance 3. 将uniqueInstance指向分配的内存地址 但是由于 JVM 具有指令重排的特性,执⾏顺序有可能变成 1->3->2。指令重排在单线程环境下不会 出现问题,但是在多线程环境下会导致⼀个线程获得还没有初始化的实例。例如,线程 T1 执⾏了 1 和 3,此时 T2 调⽤getUniqueInstance () 后发现uniqueInstance不为空,因此返回uniqueInstance ,但此时uniqueInstance还未被初始化。

这种⽅式实现起来较麻烦,但同样线程安全,⽀持延时加载。

相关推荐
聪明的笨猪猪22 分钟前
Java Redis “Sentinel(哨兵)与集群”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
222you30 分钟前
Mybatis(1)
java·tomcat·mybatis
靠近彗星36 分钟前
1.5操作系统引导
java·linux·服务器·操作系统
瑶山1 小时前
社区版Idea怎么创建Spring Boot项目?Selected Java version 17 is not supported. 问题解决
java·spring boot·intellij-idea·创建项目
学习编程的Kitty1 小时前
JavaEE初阶——多线程(1)初识线程与创建线程
java·开发语言·java-ee
长安城没有风2 小时前
从入门到精通【Redis】初识Redis哨兵机制(Sentinel)
java·数据库·redis·后端
蒂法就是我2 小时前
java集合类的底层类是哪个
java·开发语言
Hoking2 小时前
LangChain4j集成SpringBoot接入百炼大模型(Qwen)
java·人工智能·spring boot·llm
浪里小白龙592 小时前
零信任平台接入芋道框架
java
代码匠心3 小时前
从零开始学Flink:流批一体的执行模式
java·大数据·后端·flink·大数据处理