前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 史上最全单例模式实现大全

Java 史上最全单例模式实现大全

原创
作者头像
疯狂的KK
发布2024-05-10 11:49:08
1510
发布2024-05-10 11:49:08
举报
文章被收录于专栏:AI绘画Java项目实战AI绘画

引言

作为一名资深的 Java 架构师,我对单例模式可以说是了如指掌。这种设计模式无疑是 Java 开发中最常用也最重要的模式之一,它可以帮助我们控制对象的创建,保证全局唯一性,并且能够避免不必要的资源消耗。但是,你知道单例模式究竟有多少种实现方式吗?相信很多读者对此都不太清楚。

今天,我要为大家揭开单例模式的神秘面纱,带你彻底掌握所有单例模式的实现技巧。无论是懒汉式、饿汉式,还是双重检查锁、静态内部类,甚至是枚举单例,通通都在我的掌握之中。看完本文,相信你一定会成为单例模式的行家里手,成为万千程序员中的明星。那么,让我们一起开始这场精彩纷呈的单例模式之旅吧!

单例模式(Singleton Pattern)是最常用的设计模式之一,它确保某个类只有一个实例,并提供一个全局访问点。这种模式适用于以下场景:

  1. 某些类只应该有一个实例,比如配置类、日志类等。
  2. 当实例化需要消耗大量资源时,如数据库连接池、线程池等。
  3. 当多个实例会导致问题时,如共享访问修改同一个资源。

实现单例模式的关键在于:

  1. 私有化构造函数,防止外部直接创建实例。
  2. 提供一个静态的访问入口,返回唯一的实例。
  3. 保证线程安全,确保只有一个实例被创建。

下面,让我们一一探讨各种单例模式的实现方式。

单例模式的实现方式

1. 懒汉式单例模式

代码语言:java
复制
public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {
        // 私有化构造函数
    }

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

    // 其他方法...
}

这是单例模式最简单的实现方式,也被称为"懒汉式"。在第一次调用 getInstance() 方法时,才会创建唯一的实例对象。

这种方式的优点是延迟加载,节省资源。但是在多线程环境下,如果两个线程同时检查实例是否为 null,可能会创建出多个实例,违背了单例模式的设计原则。因此,这种实现方式通常不建议使用。

2. 线程安全的懒汉式单例模式

代码语言:java
复制
public class ThreadSafeLazySingleton {
    private static volatile ThreadSafeLazySingleton instance;

    private ThreadSafeLazySingleton() {
        // 私有化构造函数
    }

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

    // 其他方法...
}

为了解决多线程环境下的线程安全问题,我们可以对 getInstance() 方法加上 synchronized 关键字,确保同一时刻只有一个线程可以访问该方法。

这种实现方式能够保证线程安全,但是由于加锁操作会带来性能开销,因此在高并发场景下可能会成为性能瓶颈。

3. 双重检查锁单例模式

代码语言:java
复制
public class DoubleCheckLockingSingleton {
    private static volatile DoubleCheckLockingSingleton instance;

    private DoubleCheckLockingSingleton() {
        // 私有化构造函数
    }

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

    // 其他方法...
}

双重检查锁单例模式是对线程安全的懒汉式单例模式的优化。它先进行一次实例检查,如果实例为 null,才会进行加锁操作。这样可以大大减少不必要的同步开销,提高性能。

需要注意的是,这种实现方式需要将 instance 变量声明为 volatile,以确保多个线程能够正确地感知实例的创建过程。

4. 静态内部类单例模式

代码语言:java
复制
public class StaticInnerClassSingleton {
    private StaticInnerClassSingleton() {
        // 私有化构造函数
    }

    private static class SingletonHolder {
        private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
    }

    public static StaticInnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }

    // 其他方法...
}

静态内部类单例模式利用 Java 类的加载机制来保证线程安全。当 StaticInnerClassSingleton 类被加载时,内部类 SingletonHolder 不会被立即加载。只有在调用 getInstance() 方法时,才会触发 SingletonHolder 的加载,此时 INSTANCE 实例也被创建。

这种方式既能保证线程安全,又能做到延迟加载,并且不需要使用 synchronized 关键字,性能较好。这也是目前公认的最优秀的单例模式实现方式之一。

5. 枚举单例模式

代码语言:java
复制
public enum EnumSingleton {
    INSTANCE;

    // 其他方法...
}

枚举单例模式是使用 Java 枚举特性实现的单例模式。通过私有构造函数和枚举的特性,可以确保只有一个实例被创建。

这种实现方式非常简单,并且天生就是线程安全的。此外,它还能防止反序列化破坏单例,以及防止通过反射的方式创建新实例。因此,它被认为是最安全和最简单的单例模式实现方式。

6. 登记式/容器式单例模式

代码语言:java
复制
public class ContainerSingleton {
    private static final Map<String, Object> singletonMap = new HashMap<>();

    private ContainerSingleton() {
        // 私有化构造函数
    }

    public static void registerSingleton(String key, Object instance) {
        if (key != null && instance != null) {
            if (!singletonMap.containsKey(key)) {
                singletonMap.put(key, instance);
            }
        }
    }

    public static Object getSingleton(String key) {
        return singletonMap.get(key);
    }
}

登记式/容器式单例模式将所有的单例对象统一管理在一个 Map 中。通过 registerSingleton() 方法注册单例对象,通过 getSingleton() 方法获取单例对象。

这种方式的优点是可以管理多个单例对象,并且可以根据需要动态注册和获取。但它也需要手动管理单例对象的注册和获取,增加了使用的复杂度。

7. 序列化和反序列化的单例模式

当一个单例类实现了 Serializable 接口时,反序列化可能会破坏单例。为了解决这个问题,我们需要在单例类中添加 readResolve() 方法:

代码语言:java
复制
public class SerializableSingleton implements Serializable {
    private static final long serialVersionUID = 1L;

    private static final SerializableSingleton INSTANCE = new SerializableSingleton();

    private SerializableSingleton() {
        // 私有化构造函数
    }

    public static SerializableSingleton getInstance() {
        return INSTANCE;
    }

    private Object readResolve() {
        return INSTANCE;
    }
}

readResolve() 方法中,我们返回预先创建好的 INSTANCE 对象,这样就可以确保反序列化得到的是同一个单例对象。

8. 多例模式

除了单例模式,有时我们也需要控制类的实例数量,但不是一个,而是多个。这就用到了多例模式:

代码语言:java
复制
public class Multiton {
    private static final Map<String, Multiton> instances = new HashMap<>();

    private Multiton() {
        // 私有化构造函数
    }

    public static synchronized Multiton getInstance(String key) {
        if (!instances.containsKey(key)) {
            instances.put(key, new Multiton());
        }
        return instances.get(key);
    }
}

在这个例子中,我们使用 Map 来存储多个 Multiton 实例,并提供 getInstance() 方法来获取指定 key 对应的实例。这种模式适用于需要管理多个共享资源的场景,例如数据库连接池、线程池等。

单例模式的应用场景

单例模式广泛应用于各种 Java 应用程序中,以下是一些典型的应用场景:

  1. 日志记录器:通常系统中只需要一个日志记录器实例,用于集中管理日志信息。
  2. 配置管理:应用程序的配置信息通常应该由单个实例管理,以确保配置的一致性。
  3. 缓存:缓存数据的共享访问可以使用单例模式实现。
  4. 线程池:线程池通常由单例管理,以控制线程的生命周期和资源分配。
  5. 数据库连接池:数据库连接池也是典型的单例模式应用,用于管理数据库连接资源。
  6. 对话框:GUI 应用程序中的对话框通常应该是单例的,以避免创建多个对话框实例。
  7. 注册中心:服务注册中心通常使用单例模式来保证全局唯一性。

可以看到,单例模式是一种非常实用和广泛应用的设计模式。合理使用单例模式可以帮助我们更好地管理应用程序的资源和状态,提高程序的性能和可靠性。

总结

通过本文的详细介绍,相信大家已经对单例模式有了全面的了解。从最基本的懒汉式和饿汉式,到线程安全的双重检查锁和静态内部类,再到防止序列化破坏的枚举单例,应有尽有。此外,我们还介绍了登记式/容器式单例模式和多例模式,为你提供了更多的实现选择。

单例模式无疑是 Java 开发中不可或缺的利器。合理应用单例模式,不仅可以解决资源管理和状态控制的问题,还能提升程序的性能和可靠性。相信通过本文的学习,你一定能成为单例模式的行家里手,在未来的 Java 开发中大展拳脚。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 单例模式的实现方式
    • 1. 懒汉式单例模式
      • 2. 线程安全的懒汉式单例模式
        • 3. 双重检查锁单例模式
          • 4. 静态内部类单例模式
            • 5. 枚举单例模式
              • 6. 登记式/容器式单例模式
                • 7. 序列化和反序列化的单例模式
                  • 8. 多例模式
                  • 单例模式的应用场景
                  • 总结
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                  http://www.vxiaotou.com