设计模式 -- 单例模式

单例模式:

  目的:

    确保系统中一个类只产生一个实例。

  好处:

    1.对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销。

    2.由于new操作的次数减少,因而对系统内存的使用频率也会降低,减轻GC压力,缩短GC的停顿时间。

  单例模式的角色:

角色 作用
单例类 提供单例的工厂,返回单例
使用者 获取病使用单例类

  代码实现:

    

public class Singleton {
    private Singleton(){}
    private static Singleton instance = new Singleton();
    public static Singleton() {
        return instance;
    }
}    

上述的单例实现,可以确保一个系统中只有一个实例。但是却有另外一个问题,就是由于实例成员变量是static,因此JVM在加载单例类时,单例对象就会被创建。

如果单例类此时还承载着其他用途,那么不管这个单例类是否会被用到,都会初始化这个单例变量。

如下的代码:

  

复制代码
public class Singleton {
    private Singleton() {
        System.out.println("Singleton is create");
    }
    private static Singleton instance = new Singleton();
    private static Singleton getInstance() {
        return instance;
    }

    /**
    * 模拟单例类中扮演其他角色
    */
    public static void createString() {
        System.out.println("createString in Singleton");
    }
}
复制代码

当在main方法中尝试调用createString方法时,会看到私有构造中的打印语句被输出了,说明在调用createString时实例化了instance变量。

这也许并不是你想要的结果,如果我们希望对象在使用时再被创建,那么就需要引入延时加载的机制:

复制代码
public class LazySingleton {
    private LazySingleton(){
        System.out.println("LazySingleton is create");
    }
    private static LazySingleton instance = null;
    public static synchronized LazySingleton getInstance() {
        if(null == instance) {
            instance = new LazySingleton();
        }
        return instance;
    }

    public static void createString() {
        System.out.println("createString");
    }
}
复制代码

上述的代码实现了延时加载,同时在获取实例的方法中加入了synchronized关键字,为了确保在多线程环境下的线程安全问题。

但是同样由于synchronized关键字,它的耗时也要远远多于第一种。

为了延时加载,而降低了系统性能有点得不偿失。所以在此改进单例代码:

复制代码
public class Singleton {
    private Singleton(){}
    private static class SingletonHolder {
        private static Singleton instance = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}
复制代码

上述的代码采用内部类的形式来实现单例代码,首先,单例对象在内部类中进行实例化,而内部类只有在调用getInstance方法时才会被调用一次。从而实现了延时加载。

而且由于java内部类的加载是线程安全的,同时也解决了多线程下单例的问题。

 

posted @   框架搬运工  阅读(384)  评论(0编辑  收藏  举报
编辑推荐:
· 一文彻底搞懂 MCP:AI 大模型的标准化工具箱
· 电商平台中订单未支付过期如何实现自动关单?
· 用 .NET NativeAOT 构建完全 distroless 的静态链接应用
· 为什么构造函数需要尽可能的简单
· 探秘 MySQL 索引底层原理,解锁数据库优化的关键密码(下)
阅读排行:
· 短信接口被刷爆:我用Nginx临时止血
· 面试官:如果某个业务量突然提升100倍QPS你会怎么做?
· .NET 平台上的开源模型训练与推理进展
· 聊聊智商税:AI知识库
· 深感一无所长,准备试着从零开始写个富文本编辑器
点击右上角即可分享
微信分享提示