单例模式的三个必要条件:私有静态成员变量(这个类的引用),私有函数,获取这个静态成员变量的方法
一是某个类只能有一个实例;
二是它必须自行创建这个实例;
三是它必须自行向整个系统提供这个实例。
写eagersingleton时候,你可能这样写:
public class EagerSingleton {
private static final EagerSingleton SINGLETON = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getSingleton() {
return SINGLETON;
}
}
你是不是在想,lazysingleton可以模仿eagersingleton:
public class LazySingleton {
private static LazySingleton singleton = null;
private LazySingleton() {
System.out.println("构造函数被调用");
}
public static LazySingleton getSingleton() {
if (singleton == null) {
singleton = new LazySingleton();
}
return singleton;
}
}
很明确地告诉你,这中写法不符合singleton的要求,为什么?Let me show you now
当遇到多线程的时候,就出问题了,看图吧
那简单啊,在getSingleton()方法前面加个锁就解决问题了:
public class LazySingleton {
private static LazySingleton singleton = null;
private LazySingleton() {
System.out.println("构造函数被调用");
}
synchronized public static LazySingleton getSingleton() {
if (singleton == null) {
singleton = new LazySingleton();
}
return singleton;
}
}
的确问题解决了,但是这样貌似不太好。因为每次调用的getSingleton()方法的时候都会进行线程锁定判断,在多线程高并发的条件下,将会导致系统的性能大大降低。
最终的解决办法是,double check:
public class LazySingleton {
private static LazySingleton SINGLETON = null;
private LazySingleton() {
System.out.println("构造函数被调用");
}
public static LazySingleton getSingleton() {
// 1st check
if (SINGLETON == null) {
synchronized (LazySingleton.class) {
// 2nd check
if (SINGLETON == null) {
SINGLETON = new LazySingleton();
}
}
}
return SINGLETON;
}
}
看吧什么问题也没有