两种线程安全的单例模式

介绍

单例:保证一个类最多仅有一个实例,并提供一个全局访问点

单例模式是一种常用的软件设计模式之一,其目的是保证整个应用中只存在类的唯一实例

应用场景 —— 比如加载一些公共的配置信息,在应用程序的整个生命周期中都可见且唯一,这时需要设计成单例模式。如:spring容器,session工厂,缓存,数据库连接池等等

关键设计点

  1. 由类本身进行实例化并防止从外部实例化
  2. 对外提供获取实例的方法

一、饿汉式

class SingleInstance {
    //  在静态初始化器(static initializer)中创建单例,这保证了线程安全
    private static final SingleInstance singleton = new SingleInstance();

    public static SingleInstance getSingleton() {
        return singleton;
    }

    private SingleInstance() {
    }
}

优点 —— 获取实例速度快;线程安全

缺点 —— 类加载时就初始化实例,内存浪费

二、懒汉式

class LazySingleInstance {
    private static volatile LazySingleInstance singleton;

    private LazySingleInstance() {
    }

    //  双重检查加锁
    public static LazySingleInstance getInstance() {
        if (singleton == null) {
            synchronized (LazySingleInstance.class) {
                if (singleton == null) {
                    singleton = new LazySingleInstance();
                }
            }
        }
        return singleton;
    }
}

优点 —— 进行双重检查,保证只在实例未初始化前进行同步,效率高;线程安全

缺点 —— 每次获取实例都要进行非空检查,浪费系统资源

小结

实际上,很多程序,尤其是Web程序,大部分服务类都应该被视作Singleton

如果全部按Singleton的写法去写,会非常麻烦

所以,通常是通过约定让框架(例如Spring)来实例化这些类,保证只有一个实例,调用方自觉通过框架获取实例而不是借助new操作符

评论或私信站长


  1. #该文章暂时没有评论