单例模式
- 1)简介
- 单例对象的类只允许一个实例存在,并提供一个全局访问点。
- 2)使用场景
- 有些对象只需要一个的时候,比如线程池、缓存、日志对象等。如果制造出多个实例,就会导致许多问题的产生。
- 3)为什么不使用全局变量 ?
- 虽然Java的静态对象可以做到,但如果将对象赋值给一个全局变量,那么我们必须在程序一开始就创建好对象。而恰巧这个对象非常消耗资源,程序在这次运行过程中又一直没有用到它,就会形成浪费。如果我们利用单例模式,我们就可以在需要时才创建对象(延迟实例化)。
最基本实现(懒汉式)
public class Singleton {
private static Singleton uniqueInstance; //利用静态对象记录类的唯一实例
private Singleton() {} //私有构造器
//利用getInstance()方法实例化对象,并返回实例
public static Singleton getInstance() {
if(uniqueInstance == null) {
uniqueInstance= new Singleton();
}
return uniqueInstance;
//其他方法……
}
- 私有的构造器可以确保无法从外部创建实例,只能够通过getInstance()方法创建实例。如果我们不需要这个实例,它就永远不会产生,这就是上文中所说的“延迟实例化”。
- 这只是最基本的实现,它不支持多线程,因为没有加锁 synchronized。当有多个线程同时调用getInstance()方法时,就有可能创建出多个实例。
线程安全的实现(“双重检查加锁”)
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static getInstance() {
if(uniqueInstance == null) { //只有第一次实例化时,才会彻底执行以下的代码
synchronized (Singleton.class) {
if(uniqueInstance == null) { //加入区块后,再检查一次
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
总结
文中共提到了两种实现单例模式的方式(一种线程不安全的懒汉式实现,一种线程安全的双锁式实现)。关于单例模式还有更多种的实现方式,当考虑使用何种方式时,这需要先确定在性能和资源上的限制,然后再选择适合自己的程序的方式去实现。