专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

设计模式之单例模式

在啃Spring的源码时,看到Spring IoC容器实例化Bean中采用了单例模式,学习一下单例模式。

在单例模式下要用私有构造器:
  私有构造器,就是用private关键字声明的构造器。与一般公有构造器最大的区别在于,其访问权限是private,它只能被包含它的类自身所访问,而无法在类的外部调用,故而可以阻止外部实例化对象。

public class Singleton {
    private static Singleton uniqueInstance;
    private Singleton() {
    }
    public static Singleton getUniqueInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
}

这是一个线程不安全的单例,因为如果多个线程能够同时进入 if (uniqueInstance == null) ,并且此时 uniqueInstance 为 null,那么多个线程会执行 uniqueInstance = new Singleton(); 语句,这将导致多次实例化 uniqueInstance。


可以对getUniqueInstance() 方法加锁:

public class Singleton {
    private static Singleton uniqueInstance;
       private Singleton() {
       }
       public static synchronized Singleton getUniqueInstance() {
       if (uniqueInstance == null) {
           uniqueInstance = new Singleton();
       }
       return uniqueInstance;
    }
}

这样有一个问题,就是当一个线程进入该方法之后,其它线程试图进入该方法都必须等待,因此性能上有一定的损耗。


采用双重校验锁先判断 uniqueInstance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁。

public class Singleton {
    private volatile static Singleton uniqueInstance;
    private Singleton() {
    }
    public static Singleton getUniqueInstance() {
        if (uniqueInstance == null) {
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

如果只有单层判断:

if (uniqueInstance == null) {
    synchronized (Singleton.class) {
        uniqueInstance = new Singleton();
    }
}

在 uniqueInstance == null 的情况下,如果两个线程同时执行if语句,那么两个线程就会同时进入if语句块内。虽然在if语句块内有加锁操作,但是两个线程都会执行uniqueInstance = new Singleton(); 这条语句,只是先后的问题,也就是说会进行两次实例化,从而产生了两个实例。
注意一定要加volatile关键字,原因可以参考博主总结的这篇文章


Effective Java作者Josh Bloch 提倡使用枚举的方式,因为创建一个enum类型是线程安全的。这种方法在功能上与公有域方法相近,但是它更加简洁,无偿提供了序列化机制,绝对防止多次实例化,即使是在面对复杂序列化或者反射攻击的时候。

public enum Singleton {
    uniqueInstance;
}

关于枚举类的详解,可以参考这篇文章

文章永久链接:https://tech.souyunku.com/48592

未经允许不得转载:搜云库技术团队 » 设计模式之单例模式

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们