单例模式(Singleton Pattern)

单例模式,即限制类只能实例化一个实例的设计模式a software design pattern that restricts the instantiation of a class to a singular instance.

通常而言单例模式满足以下特征:

  • 确保只有一个实例Ensure they only have one instance
  • 提供获取该实例的途径Provide easy access to that instance
  • 控制实例化的过程(比如私有化构造器)Control their instantiation (for example, hiding the constructors of a class)

映射至现实世界,假设一个办公室的所有手机都有连接WiFi的需求,那么并不需要为每部手机提供一个WiFi,而是一个WiFi供所有手机使用,那么这个WiFi就是单例模式。显而易见,这样的设计大大节省了资源!

追溯至Spring的代码世界,IOC容器就是单例模式的一种著名的具体实现,@Controller、@Service、@Component、@Configuration、@Bean等方式注入至IOC容器的Bean,通常都由IOC进行实例化管理,并通过@Autowired、@Resource、构造器等方式方便的拿取并使用。

 

但是除了IOC实现单例模式之外,还有如下两种常见实现:

  • 1️⃣双重校验锁(Double-Checked Locking,DCL)
  • 2️⃣CAS(Compare-And-Swap)

先简单谈及两者的优缺点

1️⃣严格意义的单例,多线程场景的使用下存在一定阻塞情况。2️⃣非严格意义的单例,存在重复实例化的可能,避免了锁的开销,适用于高并发场景

既然有了IOC的单例实现,为什么我们仍然需要自己来实现单例呢?比如在写一些工具类的时候,该工具类的使用频率较低,注入IOC会使得该对象没有被使用的时候无法被GC回收,从而浪费了memory。或者在某些古老的屎山项目中,你会发现只能通过xml来往IOC注入Bean……在这些特殊场景下,自定义实现单例模式,往往更方便更自主可控。

/**
 * 适用于使用频率较低的工具类 
 */
public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {
        // 初始化逻辑
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
/**
 * 高并发场景(若条件满足,请直接选择IOC的单例) 
 */
public class Singleton {
    private static final AtomicReference<Singleton> instance = new AtomicReference<>();

    private Singleton() {
        // 初始化逻辑
    }

    public static Singleton getInstance() {
        for (;;) {
            Singleton current = instance.get();
            if (current != null) {
                return current;
            }
            current = new Singleton();
            if (instance.compareAndSet(null, current)) {
                return current;
            }
        }
    }
}

 

posted @ 2024-06-25 23:47  Ashe|||^_^  阅读(6)  评论(0编辑  收藏  举报