文章目录
📝什么是单例模式
- 单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供全局访问点以访问这个唯一的实例。
- 使用单例模式的主要目的是在整个应用程序中共享数据或资源,确保只有一个实例存在,以避免重复创建相同对象的开销,并提供一种方便的访问方式。
以下是单例模式的关键要点:
- 私有的构造函数:单例模式的类通常会将构造函数设置为私有的,这样可以防止通过直接实例化类来创建多个实例。
- 静态成员变量:类中通常会包含一个静态的成员变量,该变量用于保存类的唯一实例。
- 全局访问点:类会提供一个公共的静态方法,用于访问类的唯一实例。该方法通常被命名为
getInstance()
。
下面是一个简单的单例模式的示例:
public class Singleton {
// 私有静态成员变量,用于保存唯一实例
private static Singleton instance;
// 私有构造函数,防止直接实例化
private Singleton() {}
// 全局访问点,用于获取唯一实例
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
-
在上述示例中,
Singleton
类通过将构造函数设置为私有的,防止其他类直接实例化。它包含一个静态成员变量instance
,用于保存类的唯一实例。通过getInstance()
方法,可以获取访问唯一实例的全局访问点。 -
使用单例模式时需要注意线程安全性和初始化时机的问题。在多线程环境下,需要保证线程安全,可以使用双重检查锁定等方式来实现。另外,单例模式的实例化可以在类加载时进行(饿汉式),也可以在第一次访问时进行(懒汉式)。
-
单例模式具有全局可访问的特点,因此经常用于管理共享的资源、配置信息、数据库连接等场景,以便整个系统都能共享和使用这些对象。然而,过度使用单例
📝线程安全有哪些实现方式
1️⃣饿汉式
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
2️⃣双检锁/双重校验锁(DCL,即 double-checked locking)
public class Singleton {
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
3️⃣静态内部类
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {
}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
4️⃣枚举
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
class test{
public static void main(String[] args) {
Singleton.INSTANCE.whateverMethod();
}
}
📈总结
- 饿汉方式建议使用第 1 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 3 种静态内部类方式。如果涉及到反序列化创建对象时,可以尝试使用第 4 种枚举方式。如果有其他特殊的需求,可以考虑使用第 3 种双检锁方式。
- 单例模式适用于以下场景:
- 全局访问点:当需要在整个应用程序中共享一个对象实例,并希望通过一个全局访问点进行访问时,可以使用单例模式。这样可以确保只有一个实例存在,并且可以在任何地方方便地访问该实例。
- 资源共享:某些资源在系统中是有限的,比如数据库连接池、线程池等。在这种情况下,使用单例模式可以有效地管理和共享这些资源,避免资源的重复创建和浪费。
- 配置信息:单例模式常用于管理应用程序的配置信息。通过将配置信息封装为单例实例,可以确保在整个应用程序中只有一个唯一的配置实例,并且可以方便地进行读取和修改。
- 日志记录:在日志记录系统中,通常会使用单例模式来维护一个全局的日志对象。这样可以确保在整个系统中只有一个日志实例,方便统一管理和记录日志信息。
- 需要注意的是,单例模式可能会引入全局状态,对于多线程环境下的并发访问需要特别小心处理,以避免出现竞争条件和线程安全问题。在实现单例模式时,可以采用懒加载(Lazy Initialization)或者枚举(Enum)等方式来保证线程安全和延迟初始化的需求。
- 总之,单例模式适用于那些需要在整个应用程序中共享和管理唯一实例的场景,特别是全局访问点、资源共享、配置信息、日志记录等情况下。