单例模式-三种实现【延迟实例化、急切实例化、内部类】


例:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry


核心奥义:相同条件下,最多只存在一个实例,每次使用时进行获取,获取不到时进行实例化,同一时间只允许一个线程进行实例化

延迟实例化
使用同步锁保障线程安全,同时可以使用volatile保证线程通信(数据同步)
缺点:第一次实例化时,线程需要等待,如果同时有多个请求,可能造成短暂拥堵
优点:第一次使用时才进行实例化,节省启动资源占用
在这里插入图片描述
急切实例化
在项目启动时进行实例化,由JVM保障实例唯一性
缺点:如果实例在项目启动后很长一段时间闲置,会造成资源浪费
优点:代码逻辑简单,符合大部分应用场景

public class Singleton {
 
    private volatile static Singleton uniqueInstance = new Singleton();
 
    private Singleton(){}
 
    public static Singleton getInstance(){
        return uniqueInstance;
    }

内部类
综合以上两种方式
类定义数据是存放在方法区的,静态常量是存放在方法区的运行时常量池中
缺点:内部类的潜在风险是方法区溢出,经常使用内部类,会忽视类的数量
优点:一开始不实例化,不浪费不必要的资源;内部类借助JVM保障了实例的唯一性

public class SingletonIniti {

        private SingletonIniti() {

        }

        private static class SingletonHolder {

                private static final SingletonIniti INSTANCE = newSingletonIniti();

         }

        public static SingletonIniti getInstance() {

                return SingletonHolder.INSTANCE;

        }

}
### 单例模式实现方法 #### Eager Initialization (急切初始化) 在某些情况下,如果程序总是需要实,或者创建实的成本不高,则可以选择使用急切初始化的方式。这种方式会在加载时就创建好唯一的实对象: ```java public class Singleton { private static final Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } } ``` 这种方法简明了,在多线程环境中不会出现问题,因为静态变量`instance`只被赋值一次[^2]。 #### Lazy Initialization (懒汉式初始化) 对于资源消耗较大的情况,可以采用延迟加载的方式来实现单例模式。这意味着直到第一次调用获取实的方法才会真正去创建这个唯一实。下面是一个简子展示如何通过双重检查锁定来安全地实现在多线程环境下的懒加载: ```java public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() {} public static Singleton getInstance() { if (uniqueInstance == null) { synchronized (Singleton.class) { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } } } return uniqueInstance; } } ``` 这里利用了Java中的`volatile`关键字以及同步代码块确保即使是在高并发的情况下也能正确无误地返回同一个实[^4]。 #### Factory Method Implementation (工厂方法实现) 另一种常见的做法是借助于工厂设计模式来进行管理。在这种方案里,通常会有一个专门负责生产特定型的对象的工厂,并且该工厂内部维护着所生产的每一个型对应的一实副本。当外界请求某个具体的产品时,它先尝试从缓存池中查找是否存在可用的对象;如果有则直接提供给客户端使用;如果没有的话再新造一个并加入到集合当中保存起来供后续重复利用。 ```java class ProductFactory { private Map<String, Object> products = new HashMap<>(); @SuppressWarnings("unchecked") public <T extends Product> T getProduct(Class<T> clazz) throws Exception { String key = clazz.getName(); if (!products.containsKey(key)) { T product = clazz.getDeclaredConstructor().newInstance(); products.put(key, product); } return (T) products.get(key); } } interface Product {} ``` 此段代码展示了基于泛型和反射机制构建的一个通用产品制造者接口及其部分实现逻辑[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值