前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文详细解读Java的单例模式

一文详细解读Java的单例模式

作者头像
Java极客技术
发布2024-07-31 17:29:43
2440
发布2024-07-31 17:29:43
举报
文章被收录于专栏:Java极客技术

每天早上八点,准时推送干货

我们在面试的过程中,会经常的被问到关于设计模式的相关面试题,而且各种设计模式非常的多,了不起接下来就写一下关于设计模式的文章,来总结归纳一下这个设计模式。

单例模式

Java中的单例模式(Singleton Pattern)是一种常用的设计模式,它确保一个类仅有一个实例,并提供一个全局访问点来获取该实例。

单例模式的特点

  • 唯一性:确保一个类只有一个实例。
  • 自我实例化:单例类必须自行创建自己的唯一实例。
  • 全局访问:单例类必须提供一个全局的访问点来获取该实例。

单例模式的实现方式

Java中实现单例模式有多种方式,每种方式都有其特点和适用场景。以下是几种常见的实现方式:

1.饿汉式(Eager Initialization)

  • 在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。
  • 线程安全,因为在类加载时就完成了实例的初始化,所以不存在多线程访问问题。
代码语言:javascript
复制
public class SingletonEager {  
    private static final SingletonEager instance = new SingletonEager();  
    private SingletonEager() {}  
    public static SingletonEager getInstance() {  
        return instance;  
    }  
}

2.懒汉式(Lazy Initialization,线程不安全)

  • 在真正需要使用时才进行实例化,实现了延迟加载。
  • 但在多线程环境下可能会创建多个实例,因此线程不安全。
代码语言:javascript
复制
public class SingletonLazyUnsafe {  
    private static SingletonLazyUnsafe instance;  
    private SingletonLazyUnsafe() {}  
    public static SingletonLazyUnsafe getInstance() {  
        if (instance == null) {  
            instance = new SingletonLazyUnsafe();  
        }  
        return instance;  
    }  
}

3.懒汉式(线程安全)

  • 在懒汉式的基础上,通过加锁(如使用synchronized关键字)来保证在多线程环境下的线程安全。
  • 但每次调用getInstance()方法时都会进行加锁操作,影响性能。
代码语言:javascript
复制
public class SingletonLazySafe {  
    private static SingletonLazySafe instance;  
    private SingletonLazySafe() {}  
    public static synchronized SingletonLazySafe getInstance() {  
        if (instance == null) {  
            instance = new SingletonLazySafe();  
        }  
        return instance;  
    }  
}

4.双重检查锁(Double-Checked Locking)

在懒汉式的基础上,通过双重检查锁机制来减少加锁的次数,提高性能并保证线程安全。

代码语言:javascript
复制
public class SingletonDoubleCheck {  
    private static volatile SingletonDoubleCheck instance;  
    private SingletonDoubleCheck() {}  
    public static SingletonDoubleCheck getInstance() {  
        if (instance == null) {  
            synchronized (SingletonDoubleCheck.class) {  
                if (instance == null) {  
                    instance = new SingletonDoubleCheck();  
                }  
            }  
        }  
        return instance;  
    }  
}

5.静态内部类

  • 利用类加载机制来保证单例的唯一性,同时实现了延迟加载。
  • 线程安全,且性能较好。
代码语言:javascript
复制
public class SingletonStaticInner {  
    private static class InnerClass {  
        private static final SingletonStaticInner INSTANCE = new SingletonStaticInner();  
    }  
    private SingletonStaticInner() {}  
    public static SingletonStaticInner getInstance() {  
        return InnerClass.INSTANCE;  
    }  
}

6.枚举

  • 利用Java枚举的特性来实现单例模式,天然地保证了线程安全和单例的唯一性。
  • 简洁且自动支持序列化机制,防止反序列化重新创建新的对象。
代码语言:javascript
复制
public enum SingletonEnum {  
    INSTANCE;  
    public void someMethod() {  
        // 方法实现  
    }  
}

Spring中的单例模式体现

在Spring框架中,单例模式(Singleton Pattern)扮演着至关重要的角色,尤其是在Bean的生命周期管理和依赖注入(DI)方面。Spring通过其控制反转(IoC)容器实现了单例模式,使得开发者能够轻松地在应用中管理和使用单例对象。以下是Spring中单例模式的具体体现:

Bean的作用域

Spring容器中的Bean默认就是单例(Singleton)的。这意味着当开发者定义一个Bean时,Spring容器将会创建一个单一的实例,并管理这个实例的生命周期。所有对该Bean的请求都将返回同一个实例。这种方式简化了传统单例实现的复杂性,并确保了线程安全。

依赖注入

Spring使用依赖注入来管理组件(即Beans)之间的依赖关系。当一个Bean被标记为单例时,无论它在应用中的哪个位置被注入,注入的都是同一个实例。这通过@Component、@Service、@Repository等注解实现,这些注解标记的类会被Spring自动注册为Bean,并默认以单例模式管理。

线程安全性

虽然Spring中的单例Bean是全局共享的,但Spring框架通过确保每个Bean的作用域是隔离的,从而保证了线程安全。这意味着每个Bean实例都独立于其他Bean实例,并且不会被其他Bean的线程直接访问或修改其内部状态(除非通过共享资源或方法调用进行显式共享)。

配置和扩展

开发者可以通过Spring的配置文件或注解来配置Bean的作用域。虽然默认是单例的,但也可以配置为其他作用域,如原型(Prototype)、请求(Request)、会话(Session)等。此外,Spring还允许通过实现特定的接口或继承特定的类来扩展单例模式的行为,如实现ApplicationContextAware接口以获取ApplicationContext的引用。

Spring单例Bean的示例

代码语言:javascript
复制
import org.springframework.stereotype.Component;  
  
@Component  
public class SingletonService {  
    // 类的业务逻辑  
    public void performAction() {  
        // 执行某些操作  
    }  
}  
  
// 在其他组件中注入SingletonService  
@Component  
public class AnotherComponent {  
    private final SingletonService singletonService;  
  
    @Autowired  
    public AnotherComponent(SingletonService singletonService) {  
        this.singletonService = singletonService;  
    }  
  
    public void useSingletonService() {  
        singletonService.performAction();  
    }  
}

单例模式的优点与缺点

优点

  • 节省资源:由于只有一个实例,可以节省系统资源。
  • 提高性能:避免频繁创建和销毁对象带来的性能开销。
  • 方便管理:可以对实例进行集中的管理,如配置信息、线程池等。

缺点

  • 扩展性差:单例类通常没有接口,不便于扩展。
  • 测试不利:在单例类中进行单元测试时,可能会因为只有一个实例而带来不便。

关于单例模式你学会了么?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java极客技术 微信公众号,前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单例模式
    • 单例模式的特点
    • 单例模式的实现方式
    • Spring中的单例模式体现
      • Bean的作用域
        • 依赖注入
          • 线程安全性
            • 配置和扩展
            • 单例模式的优点与缺点
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档