线程安全 比较好的一种写法
且利用 jvm的双亲委派机制 保证线程问题(只加载一次)
缺点:不管用没用到 都会被加载到jvm中
public class EHanShiSingleton{
private static final EHanShiSingleton INSTANCE = new EHanShiSingleton();
private EHanShiSingleton(){};
public static EHanShiSingleton getInstance(){
return INSTANCE;
}
}
缺点:多线程中会被多次实例化
public class LanHanShiSingleton{
private static LanHanShiSingleton INSTANCE = null;
private LanHanShiSingleton(){};
public static LanHanShiSingleton getInstance(){
if(INSTANCE == null){
INSTANCE = new LanHanShiSingleton();
}
return INSTANCE;
}
}
缺点:还是在多线程中会被多次实例化 只是排队了
public class LanHanShiSingleton{
private static LanHanShiSingleton INSTANCE = null;
private LanHanShiSingleton(){};
public static LanHanShiSingleton getInstance(){
if(INSTANCE == null){
// 加锁
synchronized(LanHanShiSingleton.class){
INSTANCE = new LanHanShiSingleton();
}
}
return INSTANCE;
}
}
缺点:浪费资源、效率不高
public class LanHanShiSingleton{
// volatile 防止指令重排
private static volatile LanHanShiSingleton INSTANCE = null;
private LanHanShiSingleton(){};
public static LanHanShiSingleton getInstance(){
if(INSTANCE == null){
synchronized(LanHanShiSingleton.class){
// 加锁后 二次判断
if(INSTANCE == null){
INSTANCE = new LanHanShiSingleton();
}
}
}
return INSTANCE;
}
}
缺点:CAS存在忙等的问题,可能会造成CPU资源的浪费。
public class LanHanShiSingleton{
private static final AtomicReference<LanHanShiSingleton> INSTANCE = new AtomicReference<>();
private LanHanShiSingleton(){};
public static LanHanShiSingleton getInstance(){
for(;;){
if(INSTANCE.get()==null){
LanHanShiSingleton NEW_INSTANCE = new LanHanShiSingleton();
INSTANCE.compareAndSet(null,NEW_INSTANCE);
}
}
return INSTANCE.get();
}
}
利用 内部类 实现懒加载
利用 jvm的双亲委派机制 保证不会在多线程中重复加载
public class Singleton{
private Singleton() {}
private final static GetSingleton() {
private final static Singleton INSTANCE = new Singleton();
}
private static Singleton getInstance(){
return GetSingleton.INSTANCE;
}
}
利用枚举类实现单例模式。
同时枚举类也自动提供了序列化机制,只是枚举类无法实现继承,所以如果想要扩展就需要通过接口的方式实现。
public enum Singleton{
INSTANCE;
}