序言
单例(Singleton) 是指那些仅仅被初始化一次的类。
如这样
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {
}
public void leaveTheBuilding(){
}
}
私有的构造器在类被加载的时候,只运行了一次,用来实例化 final 域的 INSTANCE
。(不推荐有安全因素),除此之外还有几种常见的构建单例的方式。
饿汉模式
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
public static Elvis getINSTANCE() {
return INSTANCE;
}
private Elvis() {
}
public void leaveTheBuilding() {
}
}
还可以加入一个 getINSTANCE()
方法,这种方式呢就是之前所说的静态工厂构造, 使用 private static final 则使 INSTANCE
在初始化的时候具有绝对的线程安全。
懒汉的双重加锁机制
public class Elvis {
private volatile static Elvis INSTANCE;
public static Elvis getINSTANCE() {
if (INSTANCE == null) {
synchronized (Elvis.class) {
if (INSTANCE == null) {
INSTANCE = new Elvis();
}
}
}
return INSTANCE;
}
private Elvis() {
}
public void leaveTheBuilding() {
}
}
volatile 关键字确保,当 INSTANCE
变量被初始化成Elvis实例时,多个线程正确地处理INSTANCE
变量
静态内部类
public class Elvis {
private static class LazyHolder {
private static final Elvis INSTANCE = new Elvis();
}
public static Elvis getINSTANCE() {
return LazyHolder.INSTANCE;
}
private Elvis() {
}
public void leaveTheBuilding() {
}
}
序列化问题
上述所有构建单例的方式都有 序列化的问题,因此在实现 Serializable 的同时呢还有加入一个 readResolve方法,否则每一次反序列化都会产生一个新的实例。
private Object readResolve(){
return INSTANCE;
}
枚举单例
枚举单例就厉害了,无偿提供了序列化机制,绝对防止多次实例化!!!
public class Elvis {
enum SingletonEnum {
INSTANCE;
private Elvis elvis;
SingletonEnum() {
elvis = new Elvis();
}
public Elvis getInstnce() {
return elvis;
}
}
public static Elvis getINSTANCE() {
return SingletonEnum.INSTANCE.getInstnce();
}
private Elvis() {
}
public void leaveTheBuilding() {
}
}
单例枚举已经成为实现单例的最佳方法。