单例模式很好理解,就是对象只有一个唯一的实例,实际工程中,有很多例子,比如:线程池、缓存、日志对象等。那么如何实现单例模式呢?我们先来看一下经典的实现方法:
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
简单地用了一下延迟初始化就实现了单例模式,但是这个方法是有很大问题的,在多线程的环境下,延迟加载就会导致出现多个实例,怎么解决这个问题呢?这个应该很快能想到,加一个synchronized 嘛!
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
的确,线程不安全的问题得到了解决,但是性能问题又冒头了,每次调用getInstance方法的时候都只能一个线程进入该方法,会导致性能大大地下降!那么怎么平衡线程安全与性能呢?用“双重检查加锁”吧!
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
这次改变了synchronized 关键字的修饰粒度,直接导致了只需要第一次创建实例的时候会进入synchronized 代码块,以后调用的时候就不用了,大大提高了性能。