单例模式的几种实现方式

单例模式(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还未被初始化。

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

相关推荐
程序员黑豆4 小时前
AI全栈开发 - Java:变量
java·前端·ai编程
我是一颗柠檬4 小时前
【Java项目技术亮点】分库分表+数据路由策略:单表5000万后的架构升级方案
java·开发语言·分布式·架构
布朗克1684 小时前
25 IO流高级操作——序列化、NIO与Files工具类
java·数据库·io·nio
小研说技术4 小时前
Spring AI实现rag流程(简易版)
java·后端
亓才孓4 小时前
【本地项目引用外部库的类,想修改字段遇到的请缓存的问题】
java·maven
小林敲代码77884 小时前
记录一下IDEA中很多变量变色的方案
java·开发语言·spring boot·idea
南知意-4 小时前
IDEA 2026.1最新版安装教程
java·ide·intellij-idea·idea安装·idea激活
星子落怀aa4 小时前
Java 反复报错?Gemini助力修复
java
半夜修仙4 小时前
RabbitMQ中如何保证消息的可靠性传输
java·分布式·中间件·rabbitmq·github·java-rabbitmq
Flittly4 小时前
【AgentScope Java新手村系列】(3)工具系统
java·spring boot·spring