Java:
public final class Singleton{
private static final Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
Lazy initialization模式
- final 避免被继承
- 私有构造,保证不被外部初始化
- 第一个空判断,可以去除,但synchronized是一个重操作,锁的申请与释放都是比较耗时好资源的,所以加上之后进行性能优化。
- 第二个空判断,不可以去除,多个线程同时访问时,
- volatile字段的用处,new Singleton()创建对象可分为三步,
1)给Singleton实例分配内存
2)初始化Singleton构造器
3)将INSTANCE 对象指向分配的内存空间
注意:Java会对指令进行重排序,JVM根据处理器的特性,充分利用多级缓存,多核等进行适当的指令重排序,使程序在保证业务的同时,会重排指令。
简单讲就是上面的顺序不一定是1-2-3,也有可能是1-3-2,如果为1-3-2,当执行完1-3的时候,另一个线程访问getInstance,由于INSTANCE不为null,直接返回INSTANCE,但由于2还没有执行完,此时INSTANCE还是没有完全构造好,导致出错。
- volatile字段的用处,new Singleton()创建对象可分为三步,
public final class Singleton{
private static volatile Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
Kotlin:
object Singleton
枚举实现:
public enum Singleton {
INSTANCE;
}
实际上等同于
public enum Singleton {
INSTANCE;
// 这里隐藏了一个空的私有构造方法
private Singleton () {}
}
标准实现:
// 定义单例模式中需要完成的代码逻辑
public interface MySingleton {
void doSomething();
}
public enum Singleton implements MySingleton {
INSTANCE {
@Override
public void doSomething() {
System.out.println("complete singleton");
}
};
public static MySingleton getInstance() {
return Singleton.INSTANCE;
}
}
静态内部类:
- JVM本身保证线程安全
- 延迟加载,外部类的加载不影响内部类的加载,只有真正调用getInstance方法的时候,内部类才会加载。
public final class InnerSingleton {
private InnerSingleton(){
}
private static final class InnerSingletonHolder{
static final InnerSingleton instance = new InnerSingleton();
}
public static InnerSingleton getInstance(){
return InnerSingletonHolder.instance;
}
}
网友评论