单例模式¶
功能¶
主要作用是保证在Java程序中,某个类只有一个实例存在。一些管理器和控制器常被设计成单例模式。
实现方法¶
饿汉式¶
线程安全,无法实现实例懒加载策略。
public class Singleton1 {
private final static Singleton1 singleton1 = new Singleton1();
private Singleton1() {
}
public static Singleton1 getInstance() {
return singleton1;
}
}
懒汉式¶
线程不安全,实现了实例懒加载策略。
public class Singleton2 {
private final static Singleton2 singleton2;
private Singleton2() {
}
public static Singleton2 getInstance() {
if (singleton2 == null)
singleton2 = new Singleton2();
return singleton2;
}
}
全局锁¶
线程安全,且实现了懒加载策略,但是线程同步时效率不高。
双重校验锁式¶
线程安全,且实现了懒加载策略,同时保证了线程同步时的效率。但是volatile强制当前线程每次读操作进行时,保证所有其他的线程的写操作已完成。volatile使得JVM内部的编译器舍弃了编译时优化,对于性能有一定的影响。
静态内部类式【推荐】¶
外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存。即当SingleTon第一次被加载时,并不需要去加载SingleTonHoler,只有当getInstance()方法第一次被调用时,才会去初始化INSTANCE,第一次调用getInstance()方法会导致虚拟机加载SingleTonHoler类,这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。当getInstance()方法被调用时,SingleTonHoler才在SingleTon的运行时常量池里,把符号引用替换为直接引用,这时静态对象INSTANCE也真正被创建。
public class Singleton6 {
private Singleton6() {
}
private static class SingletonHolder {
private static final Singleton6 INSTANCE = new Singleton6();
}
public static Singleton6 getInstance() {
return SingletonHolder.INSTANCE;
}
}
枚举方式【推荐】¶
线程安全,不存在线程同步问题,且单例对象在枚举类型 INSTANCE 第一次引用时通过枚举的 构造函数 初始化,因而实现了懒加载策略。
这种方式是Effective Java作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
public class Singleton7 {
private Singleton7() {
}
enum SingletonEnum {
INSTANCE;
private final Singleton7 singleton7;
private SingletonEnum() {
singleton7 = new Singleton7();
}
}
public static Singleton7 getInstance() {
return SingletonEnum.INSTANCE.singleton7;
}
public static void main(String[] args) {
IntStream.rangeClosed(0, 100).forEach(i -> new Thread() {
public void run() {
out.println(Singleton7.getInstance());
};
}.start());
}
}