我们在单例类中添加一个该类的成员属性Instance,并提供一个getInstance方法访问它。一般来说,有如下几种实现。
饿汉式
这里的单例,是由JVM加载类时初始化生成的单例,由JVM保证了线程安全。但是耗资源,起步慢。
public class HungrySingleton {
private static HungrySingleton instance = new HungrySingleton();
public static HungrySingleton getInstance(){
return instance;
}
private HungrySingleton(){}
}
懒汉式
不是在类加载时生成,所以需要我们自己通过同步保证线程安全。通常用双重校验锁实现,是写法最复杂的方式。
public class DoubleLockSingleton {
private static volatile DoubleLockSingleton instance;
public static DoubleLockSingleton getInstance() {
if(instance == null){
synchronized (DoubleLockSingleton.class) {
if(instance == null) {
instance = new DoubleLockSingleton();
}
}
}
return instance;
}
private DoubleLockSingleton() { }
}
静态内部类实现
也是懒汉式的,写法很简洁,个人觉得是最推荐的写法。同时它也是线程安全的,因为单例是在嵌套类被加载时生成的。
public class StaticInnerSingleton {
private static class Holder{
private static StaticInnerSingleton instance = new StaticInnerSingleton();
}
public static StaticInnerSingleton getInstance(){
return Holder.instance; // 执行到这时才会加载Holder嵌套类。
}
private StaticInnerSingleton(){ }
}
枚举类
枚举自身的特性,JVM会保证线程安全和单一实例。它也是饿汉式的,枚举类加载时就会创建单例。枚举最大的优点在于可以预防反射导致的多例,因为反射无法作用于枚举类。
public enum EnumSingleton {
INSTANCE;
// 枚举类的构造函数默认是private的
EnumSingleton(){}
public void doSomething() {
// 这个类的其他方法
}
}
// 使用时直接 EnumSingleton.INSTANCE 就获取到了该类的单例。
原文:https://www.cnblogs.com/cpcpp/p/15212412.html