单例模式有多种简单的写法,饿汉式、懒汉式、单线程式等等,但考虑到多线程下的线程安全以及性能问题,推荐以下三种写法。
但是,上面提到的所有实现方式都有两个共同的缺点:
-
都需要额外的工作(Serializable、transient、readResolve())来实现序列化,否则每次反序列化一个序列化的对象实例时都会创建一个新的实例。
-
可能会有人使用反射强行调用我们的私有构造器(如果要避免这种情况,可以修改构造器,让它在创建第二个实例的时候抛异常)。
还有,不管采取何种方案,请时刻牢记单例的三大要点:
-
线程安全
-
延迟加载
-
序列化与反序列化安全
推荐写法1:
public class Singleton{
/**
* volatile(线程可见+禁止指令重排) + 双重检查锁
*/
private static volatile Singleton singleton = null;
private Singleton(){}
public static Singleton getInstance(){
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
推荐写法2:
public class Singleton{
/**
* 静态内部类(静态内部类只加载一次,
*/
private static class Holder {
private static Singleton singleton = new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return Holder.singleton;
}
}
写法3:枚举式
public enum SingletonEnum {
INSTANCE;
private String name;
public String getName(){
return name;
}
public void setName(){
this.name = name;
}
}
网友评论